如何在已经打包到左侧的现有小部件下面打包tkinter小部件?

时间:2009-09-28 04:25:57

标签: python widget tkinter pack

我正在尝试编写一个基本的Tkinter GUI,其顶部有一个Text窗口小部件,然后一个Button窗口小部件在其下面对齐,然后另一个Text窗口小部件位于按钮下方。我遇到的问题是,在将Button窗口小部件打包到左侧后,当我再打包第二个Text窗口小部件时,它将它放在右边的按钮旁边,而不是在下面按钮。无论我为第二个side小部件设置Text参数,都会发生这种情况。这是一段演示此行为的简单代码:

from Tkinter import *

root = Tk()

w = Text(root)
w.pack()

x = Button(root, text="Hi there!")
x.pack(side=LEFT)

y = Text(root)
y.pack(side=BOTTOM)

root.mainloop()

那么我该如何设置第二个Text窗口小部件,使其显示在按钮下方而不是右侧?

4 个答案:

答案 0 :(得分:15)

布局问题通常有两种解决方案:

  1. 切换到使用网格。像你想要完成的那样做布局真的很容易。网格可以解决所有布局问题的95%(当你想到它时,这是惊人的 - Tk与一位经理一起做大多数工具包需要完成的工作量!)

  2. 使用多个框架。如果某些小部件需要从上到下堆叠,而某些小部件需要从左到右堆叠,您无法始终获得所需的内容,将所有内容打包在一个框架中。布局的从上到下部分使用一个框架,从左到右内容使用其他框架。

  3. 还要意识到窗口小部件不一定是打包/网格化的窗口小部件的子窗口。您可以使用“in”参数将窗口小部件放在除父窗口之外的其他容器中。

    例如,在您的具体示例中,您可以创建三个框架,顶部,中部,底部。在顶层窗口中将这些从上到下打包。然后,您可以将顶部的第一个文本小部件,中间的水平按钮或按钮打包,并将底部的另一个文本小部件打包。

    这种方法的优势在于,它可以使未来更改布局变得更加容易(根据我的经验,总是在某些时候发生)。您不必重新设置任何窗口小部件,只需在其他容器中打包/放置/网格化即可。

    在您的简短示例中,它没有太大区别,但对于复杂的应用程序,这种策略可以节省生命。

    我最好的建议是:布局不是事后的想法。做一点计划,甚至花五分钟画一些方格纸。首先确定应用程序的主要区域,并为每个区域使用框架或其他容器(paned窗口,笔记本等)。一旦你拥有了这些,就为每个部分做同样的分而治之的方法。这使您可以为应用的不同部分使用不同类型的布局。工具栏可以获得水平布局,表单可以获得垂直布局等。

答案 1 :(得分:7)

我最初误解了包装是如何工作的,并没有意识到当我做x.pack(side=LEFT)时,整个左侧都被“声称”了。我在阅读this之后找到的内容以及Alex在这里的答案是,我根本没有将x打包到左侧,而是将其锚定左侧,使用anchor=W(西方为W)而不是side=LEFT。我修改后的代码片段完成了我的工作,如下所示:

from Tkinter import *

root = Tk()

w = Text(root)
w.pack()

x = Button(root, text="Hi there!")
x.pack(anchor=W)

y = Text(root)
y.pack(side=BOTTOM)

root.mainloop()

这种方式x不再“声称”左侧,它只是在其空间区域内与左侧(或西侧)对齐。

答案 2 :(得分:3)

打包按照调用.pack方法的顺序进行,所以一旦x“声明”了左侧,就是它 - 它将占据其父节点的左侧部分,而其父节点中的所有其他节点将是它的对。你需要一个框架来“调解”,例如....:

from Tkinter import *

root = Tk()

w = Button(root, text="Mysterious W")
w.pack()

f = Frame(root)
x = Button(f, text="Hi there!")
x.pack()

y = Button(f, text="I be Y")
y.pack(side=BOTTOM)

f.pack(side=LEFT)

root.mainloop()

(将文本更改为按钮以便更直接地查看布局 - 此Mac上的Tkinter在获得焦点之前不会清晰显示文本,但按钮非常清晰; - )。

答案 3 :(得分:0)

以与WebView使用Mosaic Canvas Widget Sets内部构件(与Tk非常相似)相同的方式进行操作。诀窍在于,第二个相同的名为Frame Object的块级浮动对象(inline:block;)对于放置在其后的所有内容以及调用“ fr”的所有内容都将自动从其内部开始。

您可以执行许多TOP对齐的小部件操作,而只需在希望在side = LEFT之间中断的地方添加另一个相同的命名Frame。在Bottom之后也可以使用。

fr=Frame(root)
fr.pack(fill=X, side=TOP)

block1=Label(fr)
block1.pack(side=LEFT)

block2=Label(fr)
block2.pack(side=LEFT)

block3=Button(fr)
block3.pack(side=LEFT)

# NAME IT THE SAME ID NAME AS THE FIRST MAIN FRAME...
fr=Frame(root)
fr.pack(fill=X, side=TOP)

# These NOW jump into the second Frame breaking the side=LEFT in new Frame
block4=Label(fr) 
block4.pack(side=LEFT)

block5=Label(fr)
block5.pack(side=LEFT)

# AND THEY CONTINUE GOING side=LEFT AFTERWARDS.