tkinter 粘性不适用于某些帧 [英] tkinter sticky not working for some frames

查看:32
本文介绍了tkinter 粘性不适用于某些帧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using tkinter to write a card game, and I'm having trouble with he grid layout manager 'sticky' configuration. I would like help fixing my code to make the frames display in the desired location. In my code and illustration below, there is a frame (b2) that contains two other (one green, b2a; and one red; b2b) frames. I would like to display frame b2 at the bottom of the parent frame (frame b). I've tried various combinations of N+S+E+W as arguments for 'sticky', for both frame b2 and the child frames b2a and b2b. However, I've been unable to make frame b2 (and more importantly b2a and b2b) appear in the desired location (the bottom image below with the correct placement was made in Illustrator).

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

In particular, it seems that sticky arguments in lines 27, 36 and 37 have no effect on the placement of frame b2, b2a and b2b inside of frame 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)

下图说明了有问题的框架(绿色和红色)显示的位置(顶部)以及我希望它们显示的位置(底部).

The images below illustrate where the offending frames (green and red) are displaying (top) and where I would like them displayed (bottom).

有人可以帮我在正确的位置显示框架 b2(最终是 b2a 和 b2b)(在框架 b 的底部,从框架 a 的右侧跨越到框架 c 的右侧)?

Could someone please help me display frame b2 (and ultimately b2a and b2b) in the correct position ( at the bottom of frame b, and spanning from the right side of frame a to the right side of frame c)?

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

Update: I've solved both problems (vertical placement and horizontal justification of frame b2) using grid weights, as Bryan suggested. The solution to the vertical placement problem is straightforward, but I would not have predicted the solution to the horizontal justification issue.

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

I solved the vertical placement problem by giving weight=1 to row 0 in frame b (resulting in the upper panel of the figure below).

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

I solved the horizontal justification problem (wherein frames b1 and b2 were not stretching to fill frame b) by assigning weight=1 to column 0 in frame b. The frame outlines in the figure below show that frame b is already stretched from the right side of frame a to the right side of frame c. It's strange to me that giving weight to the only column in a frame would be required to allow child frames to fill horizontally. In any case, I've pasted my working code below. Lines 40 and 41 solved the issue I was having.

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 的建议一致,为每个容器中的至少一列和一行分配权重似乎是一个很好的经验法则.

Consistent with Bryan's advice, it does seem to be a good rule of thumb to assign a weight to at least one column and one row in every container.

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

Here's before and after I fixed the horizontal justification problem:

使用 Python 3.4,优胜美地

Using Python 3.4, Yosemite

推荐答案

你必须给一些行和列一个权重,这样 tkinter 就知道如何分配额外的空间.

You must give some rows and columns a weight, so tkinter knows how to allocate extra space.

作为使用 grid 的经验法则,每个使用 grid 的容器都应该至少给出一行和一列的权重.

As a rule of thumb when using grid, every container using grid should give at least one row and one column weight.

我要做的就是重新开始.要有条不紊.在解决其他问题之前,先让主要的三个领域工作.使这个问题难以解决的原因是没有任何行为是正确的,所以你试图一次调整很多事情.一次专注于一个领域,让它恰到好处地工作,然后继续前进.

What I would do is start over. Be methodical. Get the main three areas working first before tackling other problems. What is making this problem hard to solve is that nothing is behaving right, so you're trying to adjust many things at once. Focus on one area at a time, get it working just right, and then move on.

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

Given your diagram, pack seems like a much simpler solution than using grid for the children of the root window Using grid inside of frames inside of other frames using grid can be confusing.

看起来框架 C 是某种横跨底部的状态栏,所以先打包它.在上面有两个区域 - 框架 a 在左边,看起来是固定的宽度,框架 c 在右边,占据了所有额外的空间.使用包,它看起来像这样:

It looks like frame C is a status bar of some sort that stretches across the bottom, so pack it first. Above that you have two areas - frame a is to the left and looks to be a fixed width, and frame c is to the right and takes up all of the extra space. Using pack, it would look like this:

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

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

Of course, you can get the exact same appearance with grid, but it will take a couple more lines of code since you have to give column 1 and row 1 a weight.

这应该可以让三个主要领域正常工作.现在您只需要担心帧 B 的内容.

That should get the three main areas working just fine. Now all you have to worry about is the contents of frame B.

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

Your diagram shows that you want b2a and b2b at the bottom of frame b, with more widgets above it. Is that correct? If that's the case, you need to leave at least one extra row above it to fill the extra space.

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

The blank row with a positive weight will force all of the widgets to be moved toward the bottom of the area. They will take up only as much space as they need vertically, with the empty row with the non-zero weight taking up all the extra.

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

You then only have to worry about horizontal placement. It's unclear exactly what you expect, but the solution again revolves around giving columns weight. If you want both b2a and b2b to expand equally, give both columns an equal weight. If you want b2a to do all of the expanding, give only column zero a weight.

这篇关于tkinter 粘性不适用于某些帧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆