当小部件跨越多个列时,如何使Tkinter列的宽度相等(Python 2.7)

当小部件跨越多个列时,如何使Tkinter列的宽度相等(Python 2.7),python,python-2.7,tkinter,tcl,tk,Python,Python 2.7,Tkinter,Tcl,Tk,在下文中,标有“1”、“2”和“THR”的按钮的间距不均匀。在我看来,问题的根源在于Tk假设任何包含跨越多个列的小部件部分的列的默认最小宽度。然而,这种行为似乎没有记录在案,因此我不确定如何适应或调整它,以使列的宽度相等-包括文本小部件跨越的两列和文本小部件未跨越的单列-从而均匀地隔开按钮。我可以通过尝试和错误来混淆它,即填充后一列,直到它与前两列匹配,但这似乎是一个糟糕的解决方案 编辑:在下面与@jwillis0720讨论之后,我添加了一个额外的列(3)和按钮(“FIV”),以使问题更清楚。这

在下文中,标有“1”、“2”和“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\u columnconfigure
uniform
不能解决此问题。插入以下行(请参见此处对类似问题的回答:)只会使列具有弹性;它们的规模仍然不均衡:

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

我想你可能想使用粘性选项

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

例如,W(west)意味着小部件应该与 左单元格边框。W+E意味着小部件应该被拉伸 水平填充整个单元格。W+E+N+S表示小部件 应该向两个方向扩展。默认设置是使小部件居中 在牢房里

编辑 它看起来像什么。我的看起来像是等距排列的,除了文本小部件占据指定的两列之外

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)

我知道这是一篇老文章,但我也很难让列和行保持一个共同的宽度/高度,所以我想我会分享我的解决方案

对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()

除了我的回答之外,我知道它起初看起来很麻烦,但是如果你继续用TKiTter构建复杂的GUI应用程序,考虑把东西放在类中并嵌入很多帧。例如,我会“观察”tkinter通过将这些按钮转换成框架,然后对其着色,来展示多少几何图形。然后我会把按钮放在框架内。@jwillis0720没有你想象的那么有用;强制使用相等的可视列宽,而不使用实际的统一组将所有内容保留在单个网格中,这真的很难。这就是为什么我们一开始就增加了制服组…@jwillis0720谢谢你关于彩色镜框的提示-我将尝试一下。不过,为了回答这个问题,我想了解一般问题,即在Tkinter的网格布局算法中,
columnspan
与列宽的关系,以及如何在没有尝试不同布局参数的反复试验过程的情况下改变或补偿这些参数。@Westcroft_to_Apse看起来只是因为文本小部件比按钮小部件占用更多的空间。因此,它将它们所在的网格推到右侧,使其看起来被压扁。我认为这只是网格管理器的一个结果。例如,检查一下如果用另一个按钮小部件替换txt框会发生什么。一切都很酷。在这种情况下,粘性的
ew
可能非常相关。我只是以NW为例,因为他们都会排队,我相信这是问题中唯一的规定。也许吧,但通常最好猜测一下他们真正想要什么,然后告诉他们。只是说,…谢谢你的回答。请注意,我并没有说我希望按钮“对齐”,但我希望它们“间隔均匀”并且“使列的宽度相等”。我可能做错了什么,但上面的代码在我运行时似乎没有实现这一点。第2列仍然比第0列和第1列窄得多,因此按钮的间距不均匀。”“等距”是一个相当模糊的短语,所以如果这混淆了问题,我很抱歉,但问题本身说的是“等宽的列”,这是我真正关心的;现在我明白了。对我来说也是这样。据我所知,均匀间距问题通过上面的
sticky='NW'
选项得以解决,只是因为不同大小的列是右侧的最后一列。但是,我的问题是如何使所有列的宽度相同,因此您的解决方案修复的是问题的影响,而不是问题本身(就我的确切示例而言,它是这样做的;它不适用于其他布局)。很抱歉,我用关于均匀间距的红鲱鱼来扩展这个问题,使事情变得混乱。这真的和上面@jwillis0720的答案一样吗?你能提供一些不同的书面解释吗?这是NAA,因为它的代码与上面几年前发布的答案完全相同
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()