【问题标题】:How to make Tkinter columns of equal width when widgets span multiple columns?当小部件跨越多列时如何使 Tkinter 列等宽(Python 2.7)
【发布时间】:2014-01-27 08:31:31
【问题描述】:

在下文中,标记为“ONE”、“TWO”和“THR”的按钮的间距不均匀。在我看来,问题的根源在于 Tk 假设任何包含跨越多列的小部件的一部分的列的默认最小宽度。但是,这种行为似乎没有记录,所以我不确定如何适应或调整它以使列具有相等的宽度 - 包括文本小部件跨越的两列和文本不跨越的单列小部件 - 从而均匀地隔开按钮。我可以通过反复试验来解决它,即填充后一列直到它与前两列匹配,但这似乎是一个糟糕的解决方案。

编辑: 在下面与@jwillis0720 的讨论之后,我添加了一个额外的列 (3) 和按钮 ('FIV') 以使问题更清晰。这个问题是关于如何在其中一些列由多列小部件跨越而其他列不跨越时获得相同宽度的列。

import Tkinter

master = Tkinter.Tk()

Tkinter.Button(master, text='ONE').grid(row=0, column=0)
Tkinter.Button(master, text='TWO').grid(row=0, column=1)
Tkinter.Button(master, text='THR').grid(row=0, column=2)
Tkinter.Button(master, text='FOU').grid(row=1, column=2)
Tkinter.Button(master, text='FIV').grid(row=0, column=3) # added as per above edit
Tkinter.Text(master).grid(row=1, column=0, columnspan=2)

master.mainloop()

请注意,将grid_columnconfigureuniform 一起使用并不能解决此问题。插入以下行(参见此处类似问题的答案:How to create equal-width columns in Python 2.7 with Tkinter)只会使列具有弹性;它们的大小仍然不均匀:

master.grid_columnconfigure(0, weight=1, uniform='a')
master.grid_columnconfigure(1, weight=1, uniform='a')
master.grid_columnconfigure(2, weight=1, uniform='a')
master.grid_columnconfigure(3, weight=1, uniform='a') # added as per above edit

【问题讨论】:

  • 除了我的回答之外,我知道一开始这似乎很麻烦,但是如果您继续使用 tkinter 构建复杂的 gui 应用程序,请考虑将内容放入类中并嵌入大量框架。例如,我会通过将这些按钮变成框架然后为它们着色来“观察”tkinter 布置了多少几何图形。然后我会把按钮放在框架内。
  • @jwillis0720 并没有你想象的那么有帮助;强制使用相等的 visual 列宽而不将所有内容保持在具有 actual 统一组的单个网格中确实很难。这就是为什么我们首先添加制服组……
  • @jwillis0720 感谢您提供有关彩色框架的提示 - 我将对此进行试验。不过,为了这个问题,我很想了解一般问题,即columnspan 与 Tkinter 的网格布局算法中的列宽相关的方式,以及如何在没有试验的情况下改变或补偿这种情况和尝试不同布局参数的错误过程。
  • @Westcroft_to_Apse 看起来只是因为文本小部件比按钮小部件占用了更多空间。因此,它将它们所在的网格推向右侧并使其看起来被压扁。我认为这只是网格管理器的结果。
  • 例如,看看如果你只是用另一个按钮小部件替换 txt 框会发生什么。一切都很酷。

标签: python python-2.7 tkinter tcl tk


【解决方案1】:

我认为您可能想要使用粘性选项。

sticky= 定义在结果单元格为 比小部件本身大。这可以是任意组合 常数 S、N、E 和 W,或 NW、NE、SW 和 SE。

例如,W(西)表示小部件应与 左单元格边框。 W+E 表示小部件应该被拉伸 水平填充整个单元格。 W+E+N+S 表示小部件 应该双向展开。默认是居中的小部件 在单元格中。

import Tkinter

master = Tkinter.Tk()

Tkinter.Button(master, text='ONE').grid(row=0, column=0, sticky='NW')
Tkinter.Button(master, text='TWO').grid(row=0, column=1, sticky='NW')
Tkinter.Button(master, text='THR').grid(row=0, column=2, sticky='NW')
Tkinter.Button(master, text='FOU').grid(row=1, column=2)
Tkinter.Text(master).grid(row=1, column=0, columnspan=2)


master.mainloop()

编辑

它看起来像什么。我的看起来像这样均匀分布,除了文本小部件按指定占用两列。

【讨论】:

  • 在这种情况下,ew 的便签可能是高度相关的。
  • 我只是以 NW 为例,因为他们都会排队,我相信这是问题中唯一的规定。
  • 也许吧,但通常最好先猜测一下他们真正想要什么,然后再告诉他们。只是说……
  • 感谢您的回答。请注意,我没有写我希望按钮“对齐”,但我希望它们“均匀分布”并且“使列具有相同的宽度”。我可能做错了什么,但是上面的代码在我运行时似乎没有实现这一点。第 2 列仍然比第 0 列和第 1 列窄得多,因此按钮的间距不均匀。 “均匀间隔”是一个相当含糊的短语,所以如果这混淆了这个问题,我很抱歉 - 但问题本身说的是“等宽的列”,这是我真正关心的问题。
  • 感谢以上编辑;现在我明白了。这也是我的样子。据我了解,上面的sticky='NW' 选项解决了均匀间距问题,只是因为不同大小的列是右边的最后一列。但是,我的问题是关于如何使所有列具有相同的宽度,因此您的解决方案修复的是问题的影响而不是问题本身(对于我的确切示例,它是这样做的;它不适用于其他布局)。我很抱歉通过扩展关于均匀间距的红鲱鱼问题来混淆问题。
【解决方案2】:

我知道旧帖子,但我也努力让列和行保持共同的宽度/高度,所以我想我会分享我的解决方案

python 和 tkinter 新手,如果有任何错误,请告诉我

我创建了一个网格管理器,这允许将主窗口和任何框架设置为具有均匀间隔的列和行,它不是 100%,但我使用它的效果很好,它在构建过程中特别有用阶段

创建框架时的一个缺点是框架的最大行数/列数必须等于或小于它所跨越的行数/列数,否则会有点奇怪(肯定为什么)

希望对你有帮助

import tkinter

class grid_manager:
    def __init__(self, Frame, colour = "gray94"):
        self.Frame = Frame
        self.Colour = colour

    def set_grid(self, numofRows, numofColumns, borderwidth = 1):
        self.numofRows = numofRows
        self.numofColumns = numofColumns
        self.borderwidth = borderwidth
        for i in range(numofRows):
            for j in range(numofColumns):
                canvas = tkinter.Canvas(self.Frame)
                canvas.config(relief="raised", borderwidth=self.borderwidth)   #comment out to hide grid layout
                canvas.grid(row=i, column=j)
                canvas.config(background=self.Colour)
                self.Frame.columnconfigure(j, weight=1)
            self.Frame.rowconfigure(i, weight=1)

mainwindow = tkinter.Tk()

mainwindow.title("Test")
mainwindow.geometry("640x480-8-200")
mainGrid = grid_manager(mainwindow)
mainGrid.set_grid(10, 10)

header_Frame = tkinter.Frame(mainwindow)
header_Frame.grid(row=0, column=0, columnspan=10, sticky="nsew")
headerGrid = grid_manager(header_Frame)
headerGrid.set_grid(numofRows=1, numofColumns=10, borderwidth=5)

footerFrame = tkinter.Frame(mainwindow)
footerFrame.grid(row=9, column=0, columnspan=10, sticky="nsew")
footerGrid = grid_manager(footerFrame, "red")
footerGrid.set_grid(numofRows=1, numofColumns=10, borderwidth=5)

rightFrame = tkinter.Frame(mainwindow)
rightFrame.grid(row=1, column=5, rowspan=5, columnspan=5, sticky="nsew")
rightGrid = grid_manager(rightFrame, "blue")
rightGrid.set_grid(numofRows=5, numofColumns=5, borderwidth=2)

leftFrame = tkinter.Frame(mainwindow)
leftFrame.grid(row=3, column=0, rowspan=5, columnspan=4, sticky="nsew")
leftGrid = grid_manager(leftFrame, "yellow")
leftGrid.set_grid(numofRows=5, numofColumns=4, borderwidth=2)

mainwindow.mainloop()

enter image description here

【讨论】:

    【解决方案3】:
    import tkinter
    
    master = tkinter.Tk()
    
    tkinter.Button(master, text='ONE                ').grid(row=0, column=3, sticky='NW')
    tkinter.Button(master, text='TWO               ').grid(row=1, column=3, sticky='NW')
    tkinter.Button(master, text='THR                ').grid(row=2, column=3, sticky='NW')
    tkinter.Button(master, text='FOU                ').grid(row=3, column=3, sticky='NW')
    tkinter.Text(master).grid(column=30, columnspan=10)
    

    【讨论】:

    • 这不是和上面@jwillis0720 的答案一样吗?您能否附上一些关于它有何不同的书面解释?
    • 这是 NAA,因为它具有与几年前发布的上述答案完全相同的代码
    猜你喜欢
    • 2019-10-30
    • 2014-01-26
    • 2014-03-09
    • 2014-07-07
    • 1970-01-01
    • 1970-01-01
    • 2015-03-10
    • 2020-06-14
    • 1970-01-01
    相关资源
    最近更新 更多