在带有画布的框架中使用grid.columnconfigure

时间:2019-06-23 13:48:22

标签: canvas tkinter

我正在使用以下代码来制作可滚动框架。现在,我希望网格中的每一列都可以水平填充整个窗口,当窗口大小改变时也是如此。

对于这种方法,我一直使用frame.grid_columnconfigure(col_num,weight = 1),并在放置元素时向.grid(row,col)命令添加了sticky =“ ew”参数。

由于某种原因(可能与画布窗口有关),这种方法在以下代码中不起作用。

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 个答案:

答案 0 :(得分:1)

问题不在于您的列是否扩展和收缩,而是它们所在的框架没有增长或缩小的事实。

要解决此问题,您需要绑定到画布的<Configure>事件。当其更改大小时,您可以强制内部框架与画布的宽度相同。

首先,建立绑定:

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

接下来,定义绑定函数以调整内部框架的宽度:

def onCanvasConfigure(self, event):
    self.canvas.itemconfigure("self.viewPort", width=event.width)