tkinter 粘性不适用于某些框架

2024-01-01

我正在使用 tkinter 编写纸牌游戏,但我在网格布局管理器“粘性”配置方面遇到了问题。我希望帮助修复我的代码以使框架显示在所需的位置。在我的代码和下面的插图中,有一个框架 (b2),其中包含另外两个框架(一个绿色,b2a;一个红色;b2b)框架。我想在父框架(框架 b)的底部显示框架 b2。对于帧 b2 以及子帧 b2a 和 b2b,我尝试了 N+S+E+W 的各种组合作为“粘性”的参数。但是,我无法使框架 b2(更重要的是 b2a 和 b2b)出现在所需的位置(下面的底部图像具有正确的位置是在 Illustrator 中制作的)。

特别是,第 27、36 和 37 行中的粘性参数似乎对帧 b2、b2a 和 b2b 在帧 b 内的放置没有影响。

from tkinter import *
from PIL import Image, ImageTk

def main(root):
    cons = Frame(root)
    cons.grid()

    frameDict = setup_frames(cons)
    populate_frames(frameDict)

def setup_frames(cons):
    frame = {}
    # Parental Frames
    frame['a'] = Frame(cons, borderwidth=2, relief='groove')
    frame['b'] = Frame(cons, borderwidth=2, relief='groove')
    frame['c'] = Frame(cons, borderwidth=2, relief='groove')

    frame['a'].grid(row=0, column=0, sticky=N+S+E+W)
    frame['b'].grid(row=0, column=1, sticky=N+S+E+W)
    frame['c'].grid(row=1, column=0, columnspan=2)

    # Progeny 0 Frames:
    frame['b1'] = Frame(frame['b'], borderwidth=2, relief='groove')
    frame['b2'] = Frame(frame['b'], borderwidth=2, relief='groove')

    frame['b1'].grid(row=0, column=0, sticky=N+S+E+W)
    frame['b2'].grid(row=1, column=0, sticky=N+S+E+W)

    # Progeny 1 Frames:

    frame['b2a'] = Frame(frame['b2'], borderwidth=2, relief='groove',
                         background='green')
    frame['b2b'] = Frame(frame['b2'], borderwidth=2, relief='groove',
                         background='red')

    frame['b2a'].grid(row=0, column=0, sticky=S)
    frame['b2b'].grid(row=0, column=1, sticky=SW)

    return frame

def populate_frames(fr):

    # Populating 'a' frame
    aLab = Label(fr['a'], image=img[0])
    aLab.grid()

    # Populating b2a & b2b frames
    bLab = Label(fr['b2a'], image=img[1])
    bLab.grid(row=0, column=0)

    bLab = Label(fr['b2b'], image=img[2])
    bLab.grid(row=0, column=1)

    # Populating c1 frame
    cLab = Label(fr['c'], image=img[3])
    cLab.grid()

if __name__ == '__main__':
    root = Tk()
    img = []
    w = [40,  160, 80, 480]
    h = [180, 60,  60, 60]
    for i in range(4):
        a = Image.new('RGBA', (w[i], h[i]))
        b = ImageTk.PhotoImage(a)
        img.append(b)
    main(root)

下图说明了违规帧(绿色和红色)的显示位置(顶部)以及我希望它们显示的位置(底部)。

有人可以帮我在正确的位置显示帧 b2 (以及最终的 b2a 和 b2b)吗(编辑:在帧 b 的底部,并从帧 a 的右侧跨越到帧 c 的右侧)?

更新: 正如 Bryan 所建议的,我已经使用网格权重解决了这两个问题(框架 b2 的垂直放置和水平对齐)。垂直放置问题的解决方案很简单,但我不会预测水平对齐问题的解决方案。

我通过给帧 b 中的第 0 行赋予权重 = 1 来解决垂直放置问题(导致下图的上面板)。

我通过将权重 = 1 分配给帧 b 中的第 0 列解决了水平对齐问题(其中帧 b1 和 b2 没有拉伸以填充帧 b)。下图中的帧轮廓显示,b 帧已经从 a 帧的右侧拉伸到 c 帧的右侧。对我来说很奇怪的是,需要对框架中唯一的列赋予权重才能允许子框架水平填充。无论如何,我已经在下面粘贴了我的工作代码。第 40 行和第 41 行解决了我遇到的问题。

from tkinter import *
from PIL import Image, ImageTk

def main(root):
    cons = Frame(root)
    cons.grid()

    frameDict = setup_frames(cons)
    populate_frames(frameDict)

def setup_frames(cons):
    frame = {}
    # Parental Frames
    frame['a'] = Frame(cons, borderwidth=2, relief='groove')
    frame['b'] = Frame(cons, borderwidth=2, relief='groove')
    frame['c'] = Frame(cons, borderwidth=2, relief='groove')

    frame['a'].grid(row=0, column=0, sticky=N+S+E+W)
    frame['b'].grid(row=0, column=1, sticky=N+S+E+W)
    frame['c'].grid(row=1, column=0, columnspan=2)

    # Progeny 0 Frames:
    frame['b1'] = Frame(frame['b'], borderwidth=2, relief='groove')
    frame['b2'] = Frame(frame['b'], borderwidth=2, relief='groove')

    frame['b1'].grid(row=0, column=0, sticky=N+S+E+W)
    frame['b2'].grid(row=1, column=0, sticky=N+S+E+W)

    # Progeny 1 Frames:

    frame['b2a'] = Frame(frame['b2'], borderwidth=2, relief='groove',
                         background='green')
    frame['b2b'] = Frame(frame['b2'], borderwidth=2, relief='groove',
                         background='red')

    frame['b2a'].grid(row=0, column=0, sticky=S)
    frame['b2b'].grid(row=0, column=1, sticky=SW)

    # Weighting
    frame['b'].grid_rowconfigure(0, weight=1)
    frame['b'].grid_columnconfigure(0, weight=1)

    return frame

def populate_frames(fr):

    # Populating 'a' frame
    aLab = Label(fr['a'], image=img[0])
    aLab.grid()

    # Populating b2a & b2b frames
    bLab = Label(fr['b2a'], image=img[1])
    bLab.grid(row=0, column=0)

    bLab = Label(fr['b2b'], image=img[2])
    bLab.grid(row=0, column=1)

    # Populating c1 frame
    cLab = Label(fr['c'], image=img[3])
    cLab.grid()

if __name__ == '__main__':
    root = Tk()
    img = []
    w = [40,  160, 80, 480]
    h = [180, 60,  60, 60]
    for i in range(4):
        a = Image.new('RGBA', (w[i], h[i]))
        b = ImageTk.PhotoImage(a)
        img.append(b)
    main(root)

与 Bryan 的建议一致,为每个容器中的至少一列和一行分配权重似乎确实是一个很好的经验法则。

这是我修复水平对齐问题之前和之后的结果:

使用Python 3.4,优胜美地


您必须为某些行和列赋予权重,以便 tkinter 知道如何分配额外空间。

使用时的经验法则grid,每个使用网格的容器应该至少给出一行和一列的权重。

我要做的就是重新开始。要有条理。先解决三个主要领域的问题,然后再解决其他问题。这个问题之所以难以解决,是因为没有任何事情表现得正确,所以你试图同时调整很多事情。一次专注于一个领域,让它正常工作,然后继续前进。

鉴于你的图表,pack似乎比对根窗口的子窗口使用网格更简单的解决方案在使用网格的其他框架内部的框架内使用网格可能会令人困惑。

看起来框架 C 是某种状态栏,延伸到底部,所以先打包它。在其上方有两个区域 - 框架 a 位于左侧,看起来具有固定宽度,框架 c 位于右侧,占据了所有额外空间。使用 pack,它看起来像这样:

frame['c'].pack(side="bottom", fill="x")
frame['a'].pack(side="left", fill="y")
frame['b'].pack(side="right", fill="both", expand=True)

当然,您可以使用网格获得完全相同的外观,但由于您必须为第 1 列和第 1 行赋予权重,因此需要多行代码。

这应该能让三个主要领域正常运转。现在您只需担心 B 帧的内容。

您的图表显示您希望 b2a 和 b2b 位于框架 b 的底部,其上方有更多小部件。那是对的吗?如果是这种情况,您需要在其上方至少留出一行来填充额外的空间。

具有正权重的空白行将迫使所有小部件向该区域的底部移动。它们只会占用垂直方向所需的空间,重量非零的空行会占用所有额外空间。

然后您只需担心水平放置。目前尚不清楚您到底期望什么,但解决方案再次围绕赋予列权重。如果您希望 b2a 和 b2b 均等扩展,请为两列赋予相同的权重。如果您希望 b2a 完成所有扩展,请仅给零列赋予权重。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

tkinter 粘性不适用于某些框架 的相关文章

随机推荐