Использование grid.columnconfigure в кадре с холстом - PullRequest
1 голос
/ 23 июня 2019

Я использую следующий код для прокручиваемого фрейма. Теперь я хочу, чтобы каждый столбец в сетке заполнял все окно по горизонтали, в том числе при изменении размера окна.

Для этого подхода я всегда использовал frame.grid_columnconfigure (col_num, weight = 1) и добавлял параметр sticky = "ew" в команду .grid (row, col) при размещении элемента.

По какой-то причине (возможно, это связано с окном Canvas), этот подход не работает в следующем коде.

import tkinter as tk

# ************************
# Scrollable Frame Class
# ************************


class ScrollFrame(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)  # create a frame (self)

        # place canvas on self
        self.canvas = tk.Canvas(self, borderwidth=0, background="#ffffff")
        # place a frame on the canvas, this frame will hold the child widgets
        self.viewPort = tk.Frame(self.canvas, background="#ffffff")
        # place a scrollbar on self
        self.vsb = tk.Scrollbar(self, orient="vertical",
                                command=self.canvas.yview)
        # attach scrollbar action to scroll of canvas
        self.canvas.configure(yscrollcommand=self.vsb.set)

        # pack scrollbar to right of self
        self.vsb.pack(side="right", fill="y")
        # pack canvas to left of self and expand to fil
        self.canvas.pack(side="left", fill="both", expand=True)
        self.canvas.create_window((4, 4), window=self.viewPort, anchor="nw",  # add view port frame to canvas
                                  tags="self.viewPort")

        # bind an event whenever the size of the viewPort frame changes.
        self.viewPort.bind("<Configure>", self.onFrameConfigure)

    def onFrameConfigure(self, event):
        '''Reset the scroll region to encompass the inner frame'''
        self.canvas.configure(scrollregion=self.canvas.bbox(
            "all"))  # whenever the size of the frame changes, alter the scroll region respectively.


# ********************************
# Example usage of the above class
# ********************************

class Example(tk.Frame):
    def __init__(self, root):

        tk.Frame.__init__(self, root)
        self.scrollFrame = ScrollFrame(self)  # add a new scrollable frame.

        # try to make the columns filling the entire frame
        self.scrollFrame.viewPort.grid_columnconfigure(0, weight=1)
        self.scrollFrame.viewPort.grid_columnconfigure(1, weight=1)

        # Now add some controls to the scrollframe.
        # NOTE: the child controls are added to the view port (scrollFrame.viewPort, NOT scrollframe itself)
        for row in range(100):
            a = row
            tk.Label(self.scrollFrame.viewPort, text="%s" % row, width=3, borderwidth="1",
                     relief="solid").grid(row=row, column=0, sticky="ew")
            t = "this is the second column for row %s" % row
            tk.Button(self.scrollFrame.viewPort, text=t, command=lambda x=a: self.printMsg(
                "Hello " + str(x))).grid(row=row, column=1, sticky="ew")

        # when packing the scrollframe, we pack scrollFrame itself (NOT the viewPort)
        self.scrollFrame.pack(side="top", fill="both", expand=True)

    def printMsg(self, msg):
        print(msg)


if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(side="top", fill="both", expand=True)
    root.mainloop()

Заранее большое спасибо за любые предложения!

1 Ответ

1 голос
/ 23 июня 2019

Проблема не в том, что ваши столбцы расширяются и сжимаются, а в том, что фрейм, в котором они находятся, не увеличивается и не уменьшается.

Чтобы решить эту проблему, вам необходимо привязать событие <Configure> к холсту. Когда он меняет размер, вы можете заставить внутреннюю рамку иметь ту же ширину, что и холст.

Сначала установите привязку:

self.canvas.bind("<Configure>", self.onCanvasConfigure)

Далее, определите связанную функцию для настройки ширины внутренней рамки:

def onCanvasConfigure(self, event):
    self.canvas.itemconfigure("self.viewPort", width=event.width)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...