Grid-Manager-Problem

Fragen zu Tkinter.
Antworten
DMD-OS
User
Beiträge: 165
Registriert: Freitag 28. Dezember 2018, 13:52

Hallo Freunde,
in meinem Code versuche ich Buttons in ein Frame in Canvas mit h-Scrollbar zu setzen.
Die Scrollbar wird eingeblendet, nur wenn sie gebraucht wird.

Code: Alles auswählen

import os
import sys
import tkinter as tk
from tkinter import ttk
from PIL import Image, ImageTk


class Selectionbar(tk.Frame):

    def __init__(self, selections_frame, preview_table):
        tk.Frame.__init__(self, selections_frame)
        self.preview_table = preview_table

        select = tk.Frame(selections_frame, bg='gainsboro')
        select.pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=4, pady=4)

        self.btn_option = tk.StringVar()
        self.btn_option.set('Datenparameter')

        auswahl_frame = tk.Frame(select, bg='gainsboro')
        auswahl_frame.pack(side=tk.LEFT)
        auswahl_frm = tk.Frame(auswahl_frame, bg='grey')
        auswahl_frm.pack(fill=tk.BOTH, expand=False, padx=8)

        self.t_btn = tk.Button(auswahl_frm,
                               text=self.btn_option.get(),
                               font=('Arial', 9, 'bold', 'italic'),
                               bg='lightsteelblue',
                               width=15,
                               command=self.btn_toggle
                               )
        self.t_btn.pack(side=tk.LEFT, padx=8, pady=8)

        ################################################
        # hier stimmt was nicht

        self.button_frm = tk.Frame(select)
        self.button_frm.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=4, pady=4)  # <----

        self.frames = {}
        for F in (Datenparameter, Datenbeziehung):
            page_name = F.__name__
            frame = F(parent=self.button_frm, controller=self)
            self.frames[page_name] = frame
            frame.grid(row=0, column=0, sticky=tk.NSEW, padx=2, pady=2)  # <---- frame wird an Datenparameter übergeben
        ################################################

        self.show_frame("Datenparameter")


    def btn_toggle(self):
        if self.btn_option.get() == 'Datenparameter':
            self.btn_option.set('Datenbeziehung')
            self.t_btn['text'] = self.btn_option.get()
            # Go to Frame 'Datenbeziehung'
            self.show_frame("Datenbeziehung")
        else:
            self.btn_option.set('Datenparameter')
            self.t_btn['text'] = self.btn_option.get()
            # Go to Frame 'Datenparameter'
            self.show_frame("Datenparameter")

    def show_frame(self, page_name):
        frame = self.frames[page_name]
        frame.tkraise()


class Datenparameter(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.parent = parent  # parent ist das übergebene frame von class Selectionbar
                              # controller ist die class Selectionbar
        self.controller = controller

        image_folder = os.path.join(os.getcwd(), "images")
        btn_dict = controller.mapping_dict['Datenparameter']

        spalten_key = list(btn_dict.keys())[0]
        spalten_values = btn_dict[spalten_key]

        self.configure(highlightbackground="lightsteelblue", highlightcolor="lightsteelblue", highlightthickness=1)

        self.canvaser = tk.Canvas(self, bg="grey", bd=1, highlightthickness=1)
        self.canvaser.grid(row=0, column=0, sticky=tk.NSEW, padx=1, pady=1)
        self.hsbar = ttk.Scrollbar(self, orient=tk.HORIZONTAL, command=self.canvaser.xview)
        self.hsbar.grid(row=1, column=0, sticky=tk.EW)
        self.canvaser.configure(xscrollcommand=self.hsbar.set)

        self.spalten_buttons = tk.Frame(self.canvaser, bg="grey")

        for button_text, button_value in spalten_values.items():
            img_info = Image.open(self.resource_LAYOUT(os.path.join(image_folder, button_value[1]))).resize((15, 15))
            image_info = ImageTk.PhotoImage(img_info)
            button = tk.Button(self.spalten_buttons,
                               image=image_info,
                               text=button_text,
                               font=('Consolas', 8),
                               compound=tk.LEFT)
            button.image = image_info
            button.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=4, pady=4)  # Volle Breite nutzen: expand=True

        self.canvaser.create_window((0, 0), window=self.spalten_buttons, anchor=tk.NW)
        self.spalten_buttons.update_idletasks()
        self.bbox = self.canvaser.bbox(tk.ALL)
        self.canvaser.configure(scrollregion=self.bbox,
                                xscrollcommand=lambda mx_f, mx_l: self.auto_scroll(self.hsbar, mx_f, mx_l)
                                )

    @staticmethod
    def resource_LAYOUT(relative_path):
        if hasattr(sys, '_MEIPASS'):
            return os.path.join(os.environ.get("_MEIPASS", os.path.abspath(".")), relative_path)
        return os.path.join(os.path.abspath("."), relative_path)

    @staticmethod
    def auto_scroll(sbar, first, last):
        first, last = float(first), float(last)
        if first <= 0 and last >= 1:
            sbar.grid_remove()
        else:
            sbar.grid()
        sbar.set(first, last)


class Datenbeziehung(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        self.configure(highlightbackground="lightsteelblue", highlightcolor="lightsteelblue", highlightthickness=1)
Das Ergebnis sieht so aus:
Bild
Die Scrollbar reagiert richtig (wird auch richtig ein- oder ausgeblendet).
Allerdings soll die Scrollbar direkt unter den Buttons sein.
Kann mir da vielleicht jmd helfen?
LG Christian
Antworten