画布中的Tkinter窗口不会以高度填充其父窗口

2024-10-01 09:32:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我想让我的滚动条在框架的底部和我的文本小部件填充整个框架以上的滚动条。我找到了一些关于宽度配置here的解决方案,但是当我试图用高度代替宽度时,它不能正确工作。在

from tkinter import *
from tkinter import ttk

class MainView(Frame):

    def FrameHeight(self, event):
        canvas_height = event.height
        self.canvas.itemconfig(self.canvas_frame, height=canvas_height)

    def OnFrameConfigure(self, event):
        self.canvas.config(scrollregion=self.canvas.bbox("all"))

    def __init__(self, *args, **kwargs):
        Frame.__init__(self, *args, **kwargs)
        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(0, weight=1)

        sensorsFrame = Frame(self)
        sensorsFrame.grid(row=0, sticky="nsew")
        sensorsFrame.grid_columnconfigure(0, weight=1)
        sensorsFrame.grid_rowconfigure(0, weight=1)

        self.canvas = Canvas(sensorsFrame)
        self.sensorsStatsFrame = Frame(self.canvas)
        self.canvas.grid_rowconfigure(0, weight=1)
        self.sensorsStatsFrame.grid_rowconfigure(0, weight=1)

        myscrollbar = Scrollbar(sensorsFrame,orient=HORIZONTAL,command=self.canvas.xview)
        self.canvas.configure(xscrollcommand=myscrollbar.set)
        self.canvas.pack(fill=BOTH, expand=1)
        myscrollbar.pack(fill=X, expand=1)

        test0 = Text(self.sensorsStatsFrame, state=DISABLED)
        test1 = Text(self.sensorsStatsFrame, width=150)
        test0.grid(column=0, row=0, sticky="nsew")
        test1.grid(column=1, row=0, sticky="nsew")

        self.canvas_frame = self.canvas.create_window((0,0),window=self.sensorsStatsFrame,anchor='nw')
        self.sensorsStatsFrame.bind("<Configure>", self.OnFrameConfigure)

        #When I try to use what i found
        #self.canvas.bind('<Configure>', self.FrameHeight)

if __name__ == "__main__":
    root = Tk()
    main = MainView(root)
    main.pack(fill="both", expand=1)
    root.wm_geometry("1100x500")
    root.wm_title("MongoDB Timed Sample Generator")
    root.mainloop()

Tags: selfeventdefrootframegridrowcanvas
2条回答

第一步:删除滚动条上下的空格

expand选项决定了tkinter如何处理未分配的空间。额外的空间将平均分配给值为1True的所有小部件。因为滚动条的值设置为1,所以会给它一些额外的空间,导致小部件的上下填充。在

相反,您需要的是将所有空间仅分配给画布。通过在滚动条上将expand设置为零来执行此操作:

myscrollbar.pack(fill=X, expand=0)

步骤2:当画布改变大小时调用函数

下一个问题是,当画布改变大小时,您希望内部框架增长,因此需要绑定到画布的<Configure>事件。在

^{pr2}$

步骤3:让画布控制内部框架的大小

不能只更改OnCanvasConfigure中内部框架的大小,因为框架的默认行为是收缩以适应其内容。在这种情况下,您希望内容展开以适合框架,而不是框架收缩以适合内容。在

有几种方法可以解决这个问题。您可以为内部帧禁用几何传播,这将阻止内部小部件更改帧的大小。或者,可以让画布强制调整帧的大小。在

第二种方法最简单。我们所要做的就是使用画布的高度作为框架高度,并使用内部文本小部件的宽度之和作为框架宽度。在

def OnCanvasConfigure(self, event):
    width = 0
    for child in self.sensorsStatsFrame.grid_slaves():
        width += child.winfo_reqwidth()

    self.canvas.itemconfigure(self.canvas_frame, width=width, height=event.height)

第四步:修复滚动条

还有一个问题要解决。如果你调整窗口的大小,你会发现如果窗口太小,tkinter会切掉滚动条。您可以通过删除调整窗口大小的功能来解决这个问题,但您的用户会讨厌这样做。在

更好的解决方案是在滚动条被切掉之前让文本小部件收缩。您可以通过调用pack的顺序来控制它。在

当没有足够的空间来容纳所有的窗口小部件时,tkinter将开始缩小窗口小部件的大小,从最后一个添加到窗口的小部件开始。在您的代码中,滚动条是最后一个小部件,但是如果您将其改为画布,滚动条将保持不变,画布将收缩(这反过来导致框架收缩,从而导致文本小部件收缩)。在

myscrollbar.pack(side="bottom", fill=X, expand=0)
self.canvas.pack(fill=BOTH, expand=1)

将包布局更改为网格布局自我.canvasmyscrollbar让它成功了。在

from tkinter import *
from tkinter import ttk

class MainView(Frame):

    def FrameHeight(self, event):
        canvas_height = event.height
        self.canvas.itemconfig(self.canvas_frame, height = canvas_height)

    def OnFrameConfigure(self, event):
        self.canvas.config(scrollregion=self.canvas.bbox("all"))

    def __init__(self, *args, **kwargs):
        Frame.__init__(self, *args, **kwargs)
        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(0, weight=1)

        sensorsFrame = Frame(self)
        sensorsFrame.grid(row=0, sticky="nsew")
        sensorsFrame.grid_rowconfigure(0, weight=1)
        sensorsFrame.grid_columnconfigure(0, weight=1)


        self.canvas = Canvas(sensorsFrame, bg="blue")
        self.sensorsStatsFrame = Frame(self.canvas)
        self.canvas.grid_rowconfigure(0, weight=1)
        self.sensorsStatsFrame.grid_rowconfigure(0, weight=1)

        myscrollbar = Scrollbar(sensorsFrame,orient=HORIZONTAL,command=self.canvas.xview)
        self.canvas.configure(xscrollcommand=myscrollbar.set)
        self.canvas.grid(row=0, sticky="nsew")
        myscrollbar.grid(row=1, sticky="nsew")

        test0 = Text(self.sensorsStatsFrame, state=DISABLED, bg="red")
        test1 = Text(self.sensorsStatsFrame, width=150)
        test0.grid(column=0, row=0, sticky="nsew")
        test1.grid(column=1, row=0, sticky="nsew")

        self.canvas_frame = self.canvas.create_window((0,0),window=self.sensorsStatsFrame,anchor='nw')
        self.sensorsStatsFrame.bind("<Configure>", self.OnFrameConfigure)
        self.canvas.bind('<Configure>', self.FrameHeight)

if __name__ == "__main__":
    root = Tk()
    main = MainView(root)
    main.pack(fill="both", expand=1)
    root.wm_geometry("1100x500")
    root.wm_title("MongoDB Timed Sample Generator")
    root.mainloop()

相关问题 更多 >