设置tk.Frame的宽度和高度

9
所以我正在创建一个GUI,并尝试使它的每个部分都适当地适应屏幕。我已经绘制了我想要GUI的每个部分看起来像什么以及它们的大小的草图,因此我知道每个元素的大概尺寸。然而,我遇到的第一个问题是设置屏幕左半部分。
因此,左半部分由一个名为MainFrame的框架组成,其中包含两个框架,我们将其称为LabelFrame和ButtonFrame。
- MainFrame需要宽度为385像素,高度为460像素。 - LabelFrame应该是375像素宽,115像素高。 - ButtonFrame需要宽度为375像素,高度为330像素。
我的问题是我不知道如何将这些尺寸设置到框架中。我尝试过self.config(width=num,height=num),显然用适当的值替换num,但这没有产生任何效果。我知道对于窗口本身有一个.geometry方法,但我还没有找到一个相应于tk.Frame的方法。

2
如果您指定了widthheight,请查看grid_propagate(0)。请注意,在这种情况下,您的框架需要在grid几何管理器下。 - CommonSense
@Skitzafreak 我认为你需要适当的行列权重来实现你需要的调整大小,而不是在你不需要的地方。请查看 columnconfigure()rowconfigure() - Mike - SMT
2
你为什么认为你的框架需要基于像素精确宽度?通常最好让tkinter根据内容决定宽度。当你开始添加超过几个占位符小部件时,UI将具有自然大小,这可能比你认为的任何大小都要好。 - Bryan Oakley
@BryanOakley 最终结果是我需要一个全屏且没有菜单栏的应用程序,且不可调整大小。因此,在进行此操作时,我有一个固定的窗口大小要求,并尝试计划在这个固定窗口上放置所有内容的位置。 - Skitzafreak
@BryanOakley 是的,我可以确定我正在创建的程序将始终在一个800x480的平板电脑屏幕上运行。 - Skitzafreak
显示剩余3条评论
3个回答

13

根据使用的几何管理器,使用grid_propagate(0)pack_propagate(0)。其中0等同于False,这告诉tkinter关闭几何传播。

默认情况下,传播是开启的,容器会随内容的大小而增长/缩小。

我假设你需要的布局如下所示:

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk

root = tk.Tk()

MainFrame = tk.Frame(root, width=385, height=460, relief='raised', borderwidth=5)
LabelFrame = tk.Frame(MainFrame, width=375, height=115, relief='raised', borderwidth=5)
ButtonFrame = tk.Frame(MainFrame, width=375, height=330, relief='raised', borderwidth=5)

some_label = tk.Label(LabelFrame, text='Simple Text')
some_button = tk.Button(ButtonFrame, text='Quit', command=root.destroy)

for frame in [MainFrame, LabelFrame, ButtonFrame]:
    frame.pack(expand=True, fill='both')
    frame.pack_propagate(0)

for widget in [some_label, some_button]:
    widget.pack(expand=True, fill='x', anchor='s')

root.mainloop()

而使用 grid 管理器,唯一不同的是循环部分(请注意 stickyrow/column configure):

...
for frame in [MainFrame, LabelFrame, ButtonFrame]:
    # sticky='nswe' acts like fill='both'
    frame.grid(sticky='nswe')
    frame.rowconfigure(0, weight=1)
    frame.columnconfigure(0, weight=1)
    frame.grid_propagate(0)

for widget in [some_label, some_button]:
    # sticky='wse' acts like fill='x' + anchor='s'
    widget.grid(sticky='wse')

root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
...

我该如何将你的代码从pack改为grid呢?.grid()方法是否也有expand和fill参数? - Skitzafreak
“grid_propagate” 几乎从来不是正确的答案。尽管它在技术上可以完成工作,但以固定宽度设计的用户界面基本上是一个糟糕的设计。 - Bryan Oakley
1
@Skitzafreak,有点类似。grid有一个sticky选项(fill='x'类似于sticky='we')。对于expand行为,您可以设置columnconfigurerowconfigure。在这里查看处理调整大小部分。[http://www.tkdocs.com/tutorial/grid.html] - CommonSense
@Bryan Oakley,当4k分辨率普及时,有人会学到你所说的教训。 - CommonSense

3

虽然我从不建议将 UI 设计成固定像素大小,但如果您正在这样做,那么最简单的解决方案是使用 placeplace 可以让您绝对控制小部件的位置和大小,并且不会导致框架因其内容而增长或缩小。

import tkinter as tk

root = tk.Tk()
root.geometry("800x480")

mainframe = tk.Frame(root, background="bisque")
labelframe = tk.Frame(mainframe, background="pink")
buttonframe = tk.Frame(mainframe, background="yellow")

mainframe.place(x=0, y=0, anchor="nw", width=385, height=460)
labelframe.place(x=0, y=0, anchor="nw", width=375, height=115)
buttonframe.place(x=0, y=116, anchor="nw", width=375, height=330)

root.mainloop()

如果您需要在不同分辨率或字体的设备上运行此代码,那么您将面临巨大的惩罚,因为重新排列所有内容将是一场噩梦。即使您的目标是固定大小的外部窗口,我个人建议在内部使用gridpack,并使用相对大小(例如:使主框架填充一半的宽度和全部高度)。


我尝试这样做的另一个原因是,当我尝试以一种使UI元素自动调整大小的方式设置窗口时,我无法正确地使其自动调整大小。它总是给我一个微小的窗口,或者当我通过root.minsize()指定屏幕大小时,我的UI元素只会出现在屏幕的一个小角落里。 - Skitzafreak
@Skitzafreak:这些问题是可以解决的,而不必诉诸于使用“place”。 - Bryan Oakley
我会发布一个新问题,更好地解释我遇到的问题。不过,我会把这里得到的信息放在我的后袋里,谢谢。 - Skitzafreak

0

我相信您正在寻找使用columnconfigure()rowconfigure()来设置列和行权重。

可以尝试像这样的代码:

import tkinter as tk


class MintApp(tk.Frame):

    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.root = parent
        self.root.columnconfigure(0, weight=0)
        self.root.rowconfigure(0, weight=0)        


        main_frame = tk.Frame(self.root, width=385, height=460, background="black")
        main_frame.columnconfigure(0, weight=0)
        main_frame.rowconfigure(0, weight=0)
        main_frame.grid(row=0, column=0)

        label_frame = tk.Frame(main_frame, width=375, height=115, background="blue")
        label_frame.grid(row=0, column=0)

        button_frame = tk.Frame(main_frame, width=375, height=330, background="green")
        button_frame.grid(row=1, column=0)



if __name__ == "__main__":
    root = tk.Tk() 
    MyApp = MintApp(root)

    tk.mainloop()

你不能使用固定的高度!证明我是错的。 - greendino
@AbdullahSaid 目标不是固定高度,而是动态地将所有内容适应屏幕。如果需要固定高度,则需要使用 grid_propagate(0) 等方法。 - Mike - SMT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接