tkinter粘性不适用于某些帧

时间:2015-08-05 22:57:02

标签: python tkinter sticky

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

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

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的右侧)?

illustration of incorrect and correct frame placement

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

我通过在第b帧的第0行给出weight = 1来解决垂直放置问题(导致下图中的上图)。

我通过在帧b中将权重= 1分配给第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)

与布莱恩的建议一致,为每个容器中的至少一列和一行指定权重似乎是一个很好的经验法则。

这是在我修正水平对齐问题之前和之后:

before and after horizontal justification

使用Python 3.4,Yosemite

1 个答案:

答案 0 :(得分:1)

你必须给一些行和列一个权重,所以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完成所有的扩展,只给第0列一个权重。