Tkinter配置列宽

9

我查看了文档并找到了3个在columnconfigure中可行的选项:

  • minsize(最小大小)
  • pad(填充)
  • weight(权重)

但是如果您想让列尽可能小怎么办?

我有3个复选框,我希望它们彼此相邻。

我发现可行的方法是:

weekly.grid(row = 2, column = 1, sticky = W)
monthly.grid(row = 2, column = 1, padx = 75, sticky = W)
yearly.grid(row = 2, column = 1, padx = 150, sticky = W)

有没有更加“优美”的方法来做这件事情呢?

值得一提的是,当使用第二列和第三列时它们之间的距离太大了 :-(

最好的问候,

Casper

1个回答

13

使用网格布局管理器的默认行为是列尽可能小,因此您不需要做任何事情(假设您正确地使用了网格)。

您描述的行为,即元素之间有太多空间,可能是由于该列中还有其他更宽的小部件。该列将默认为能够容纳最宽项目的最小宽度。或者在您的代码中,在某些列上赋予非零权重,导致它们扩展。

在我讨论解决方案之前,让我确保清楚地说明,您使用网格将多个小部件放在同一单元格中的方式绝对是错误的。没有任何理由采用这种解决方案。一个经验法则是您永远不应该将多个小部件放入单元格中。

您的最简单解决方案是将grid和pack组合使用。将所有复选框放在一个框架中,并将其放置在该框架的左侧。然后,将该框架放入grid中,并使用sticky="w"。然后,无论窗口变得多大,复选框始终会粘在其包含框架的左侧。

请注意,此解决方案不违反我之前提到的经验法则。您只在一个单元格中放置一个小部件:框架。您可以在该内部框架中放置任何内容,但从网格的角度来看,每个单元格中只有单个小部件。

以下是基于Python 2.7的工作示例:

import Tkinter as tk

class ExampleView(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        cbframe = tk.Frame(self)
        cb1 = tk.Checkbutton(cbframe, text="Choice 1")
        cb2 = tk.Checkbutton(cbframe, text="Choice 2")
        cb3 = tk.Checkbutton(cbframe, text="Choice 3")

        cb1.pack(side="left", fill=None, expand=False)
        cb2.pack(side="left", fill=None, expand=False)
        cb3.pack(side="left", fill=None, expand=False)

        # this entry is for illustrative purposes: it
        # will force column 2 to be widget than a checkbutton
        e1 = tk.Entry(self, width=20)
        e1.grid(row=1, column=1, sticky="ew")

        # place our frame of checkbuttons in the same column
        # as the entry widget. Because the checkbuttons are
        # packed in a frame, they will always be "stuck"
        # to the left side of the cell.
        cbframe.grid(row=2, column=1, sticky="w")

        # let column 1 expand and contract with the 
        # window, so you can see that the column grows
        # with the window, but that the checkbuttons
        # stay stuck to the left
        self.grid_columnconfigure(1, weight=1)

if __name__ == "__main__":
    root = tk.Tk()
    view = ExampleView(root)
    view.pack(side="top", fill="both", expand=True)
    root.wm_geometry("400x200")
    root.mainloop()

当然,您也可以将复选框放置在单独的列中 -- 这通常是最简单的方法 -- 但您可能需要让其他行中的其他项目跨越多列并处理列权重。由于根据您的描述不清楚您的问题是什么,因此上述解决方案可能对您来说是最简单的。


2
我明白了。我不知道你可以将.pack和.grid结合起来。我确实在复选框上方有一个跨列的小部件,正如你所写的那样,这可能是我的列自动变宽的原因?我会点赞并接受这个答案,因为这确实比我的解决方案更好,谢谢! :-) - Evilunclebill
在什么情况下,将Grid和Pack组合在一起是可以的?根据http://effbot.org/tkinterbook/grid.htm所述,在某些情况下,它们可能永远无法完成。 - Jacqlyn
1
@JFA:唯一的要求是您不能在具有相同父级的小部件上同时使用 grid 和 pack。 - Bryan Oakley
使用网格几何管理器的默认行为是,列将尽可能小,所以您不需要做任何事情。但是必须在某处加上一个大而粗的免责声明,即只有在其中一个列的权重设置为"1"时 ,才会自动缩小列宽。如果没有设置,则它们将保持均匀大小,至少在Python 3.6.6上我观察到的是这种行为。 - Prahlad Yeri
我认为它们并不足够宽以适应列中最宽的项目。根据我的经验,它们占用的空间比标签和按钮还要多。只有当我将一列的宽度设置为1时,其他列才变得足够宽以适应最宽的项目!(即自动收缩行为)。我在这里做错了什么吗? - Prahlad Yeri
显示剩余3条评论

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