如果取消注释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()
答案 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()