tkinter帧传播不行吗?

时间:2017-06-02 21:26:19

标签: python tkinter

如果取消注释options_frame_title,您将看到它的行为不正常。我错过了什么吗?该部分刚刚从preview_frame_title复制并粘贴,似乎没有任何问题。

from tkinter import *


blank_app = Tk()
blank_app.geometry('750x500+250+100')
blank_app.resizable(width=False, height=False)


main_frame = Frame(blank_app, width=750, height=500, bg='gray22')
main_frame.grid(row=0, column=0, sticky=NSEW)

main_title = Label(main_frame, text='App Builder', bg='gray', fg='red', font='Times 12 bold', relief=RIDGE)
main_title.grid(row=0, column=0, padx=2, pady=2, sticky=NSEW, columnspan=2)

preview_frame = Frame(main_frame, width=70, height=465, bg='red', highlightcolor='white', highlightthickness=2)
preview_frame.grid(row=1, column=0, padx=2, pady=2, sticky=NSEW)

preview_frame_title = Label(preview_frame, text='Preview Window', width=70, bg='gray', fg='blue', relief=RIDGE)
preview_frame_title.grid(row=0, column=0, sticky=NSEW)

options_frame = Frame(main_frame, width=240, height=465, bg='blue', highlightcolor='white', highlightthickness=2)
options_frame.grid(row=1, column=1, padx=2, pady=2, sticky=NSEW)

options_frame_title = Label(options_frame, text='Widget Options', width=20, bg='gray', fg='blue', anchor=CENTER, relief=RIDGE)
options_frame_title.grid(row=0, column=0, sticky=NSEW)


blank_app.mainloop()

2 个答案:

答案 0 :(得分:1)

我不明白你的意思"行为正常"。它似乎表现得像它的行为一样。

默认情况下,tkinter框架旨在缩小(或增长)以适合其子窗口小部件。当您注释掉options_frame_title.grid(...)时,框架没有可见的子项,因此它表示您给出的固定大小。当您取消注释该行时,它会使标签放置在窗口小部件中,然后使框架缩小以适应。

为了使问题更加复杂,grid默认情况下会为具有非零权重的行和列提供任何额外空间。由于您没有任何行或列任何重量,他们不会获得任何额外的空间。

部分问题在于您尝试一次解决太多问题。首次开始时,您需要更有条理。此外,当您将单个窗口小部件放入另一个窗口小部件时,应考虑使用pack。它只需要一行代码就可以用grid来填充它的父代,而不是三代。

专业提示:如果您将窗口小部件创建与窗口小部件布局分开,那么确实会有所帮助。你的代码,即使它只有几十行,但实际上很难阅读。

例如,您应该做的第一件事就是首先创建最顶层的框架,并在将任何小部件放入其中之前让它们正确填充和展开/缩小。

从头开始

第0步:不删除调整窗口大小的功能

用户不喜欢将控制权从他们手中夺走。删除这一行:

blank_app.resizable(width=False, height=False)

您的用户会感谢您,在开发过程中,您可以更轻松地使用窗口来确保所有内容都在填充,增长和缩小。

第1步:main_frame

由于它似乎包含所有内容,因此使用pack是有意义的,因为它是blank_app中唯一的小部件。

main_frame = Frame(blank_app, width=750, height=500, bg='gray22')
main_frame.pack(fill="both", expand=True)

只有这一点(加上你创建根窗口的前几行,以及对mainloop的最后调用),请注意窗口的大小是否正确,主框架是否填充了窗口。您可以根据需要调整窗口大小,主框架将继续填充整个窗口。

第2步:main_frame内的小部件

正如我之前提到的,最好将窗口小部件创建和窗口小部件布局分开。此外,在使用网格时,一个好的经验法则是始终给予至少一行和一列权重。您似乎希望右框架的宽度约为左框架的3倍。这是您可以使用权重的地方。

# widgets in the main frame
main_title = Label(main_frame, text='App Builder', bg='gray', fg='red', font='Times 12 bold', relief=RIDGE)
preview_frame = Frame(main_frame, width=70, height=465, bg='red', highlightcolor='white', highlightthickness=2)
options_frame = Frame(main_frame, width=240, height=465, bg='blue', highlightcolor='white', highlightthickness=2)

# laying out the main frame
main_frame.grid_rowconfigure(1, weight=1)
main_frame.grid_columnconfigure(0, weight=1)
main_frame.grid_columnconfigure(1, weight=3)

main_title.grid(row=0, column=0, padx=2, pady=2, sticky="nsew", columnspan=2)
preview_frame.grid(row=1, column=0, padx=2, pady=2, sticky="nsew")
options_frame.grid(row=1, column=1, padx=2, pady=2, sticky="nsew")

再一次,运行代码并注意到,当您调整主窗口大小时,一切仍然会继续填充窗口,并正确调整大小,并保持适当的比例。如果您不喜欢比例,只需更改重量即可。它们可以是您想要的任何数字。例如,如果需要,可以使用70和240。

第3步:预览框架

预览框有一个标签,我猜你会把其他东西放在标签下面。我们将继续使用grid,并将标签下方的行赋予权重,以便获得所有额外空间。添加更多小部件时,可能需要相应调整。

# widgets in the preview frame
preview_frame_title = Label(preview_frame, text="Preview Window", bg='gray', fg='blue', relief=RIDGE)

# laying out the preview frame
preview_frame.grid_rowconfigure(1, weight=1)
preview_frame.grid_columnconfigure(0, weight=1)
preview_frame_title.grid(row=0, column=0, sticky="nsew")

第4步:选项框

这就像预览框架一样:顶部是一个标签,所有额外的空间都是空行编号1.

# widgets in the options frame
options_frame_title = Label(options_frame, text='Widget Options', bg='gray', fg='blue', anchor=CENTER, relief=RIDGE)

# laying out the options frame
options_frame.grid_rowconfigure(1, weight=1)
options_frame.grid_columnconfigure(0, weight=1)
options_frame_title.grid(row=0, column=0, sticky="new")

最终版

请注意,您不必担心传播,这在某种程度上是一个高级主题。您也不必担心框架的大小,因为我们使用列权重来提供相对尺寸,并且您不必为其标签指定尺寸。

我们删除了传播代码,删除了不可调整大小的行为,并删除了一些硬编码宽度,从而减少了代码,但功能更多。

答案 1 :(得分:0)

在进行一些挖掘之后,我意识到问题不在于您的options_frame_title,而是在您的框架中放置了标签。

您取消评论options_frame_title并注释掉preview_frame_title,您会看到完全相同的问题。发生的事情是帧具有设置大小,主窗口符合该帧大小。当您决定在框架中放置标签时,框架将符合标签尺寸。

你想要实现的目标是做.grid_propagate(0)与你目前正在做的事情有点不同。

我们还需要为正确的帧添加一些权重,以便小部件正确填充。

看看这段代码。

from tkinter import *

blank_app = Tk()

main_frame = Frame(blank_app,width=700, height=300, bg='gray22')
main_frame.grid(row=0, column=0, sticky=NSEW)

main_frame.grid_propagate(0) #the only place you need to use propagate(0) Thought there are better ways

main_frame.columnconfigure(0, weight = 1) #using weights to manage frames properly helps a lot here
main_frame.columnconfigure(1, weight = 1)
main_frame.rowconfigure(0, weight = 0)
main_frame.rowconfigure(1, weight = 1)

main_title = Label(main_frame, text='App Builder', bg='gray', fg='red', font='Times 12 bold', relief=RIDGE)
main_title.grid(row=0, column=0, columnspan=2, padx=2, pady=2, sticky=NSEW)

preview_frame = Frame(main_frame, bg='red', highlightcolor='white', highlightthickness=2)
preview_frame.grid(row=1, column=0, padx=2, pady=2, sticky=NSEW)
preview_frame.columnconfigure(0, weight = 1)# using weights to manage frames properly helps a lot here

preview_frame_title = Label(preview_frame, text='Preview Window', bg='gray', fg='blue', relief=RIDGE)
preview_frame_title.grid(row=0, column=0, sticky=NSEW)

options_frame = Frame(main_frame, bg='blue', highlightcolor='white', highlightthickness=2)
options_frame.grid(row=1, column=1, padx=2, pady=2, sticky=NSEW)
options_frame.columnconfigure(0, weight = 1) #using weights to manage frames properly helps a lot here

options_frame_title = Label(options_frame, text='Widget Options', bg='gray', fg='blue', anchor=CENTER, relief=RIDGE)
options_frame_title.grid(row=0, column=0, sticky=NSEW)

blank_app.mainloop()