繁体   English   中英

画布中的Tkinter窗口未填充其父对象的高度

[英]Tkinter window in canvas doesn't fill its parent in height

我想将滚动条放在框架的底部,并将文本小部件填充到滚动条上方的整个框架。 我在这里找到了一些有关宽度配置的解决方案,但是当我尝试将宽度替换为高度时,它无法正常工作。

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()

步骤1:删除滚动条上方和下方的空间

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

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

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

步骤2:当画布更改大小时调用一个函数

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

def OnCanvasConfigure(self, event):
    <code to set the size of the inner frame>
...
self.canvas.bind("<Configure>", self.OnCanvasConfigure)

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

您不能只在OnCanvasConfigure更改内部框架的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)

步骤4:修复滚动条

还有一个问题要解决。 如果您调整窗口的大小,您会注意到如果窗口太小,tkinter将切断滚动条。 您可以通过取消调整窗口大小的功能来解决此问题,但是您的用户会讨厌此。

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

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

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

将pack布局更改为self.canvas和myscrollbar的网格布局可使其工作。

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()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM