如何在左侧已打包的控件下打包tkinter控件?
我正在尝试写一个简单的Tkinter图形界面,界面上方有一个Text
文本框,下面左侧有一个Button
按钮,然后在按钮下面还有一个Text
文本框。问题是,当我把Button
按钮放到左边后,再去放第二个Text
文本框时,它却出现在按钮的右边,而不是在按钮的下面。无论我怎么设置第二个Text
文本框的side
参数,这种情况都会发生。下面是一段简单的代码,展示了这个问题:
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 个回答
打包是按照调用.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,文本在没有获得焦点时显示得不太清楚,但按钮就很明显;-)。
我最开始对“打包”这个概念理解得不太对,没意识到当我使用 x.pack(side=LEFT)
时,整个左边的空间都被“占用了”。在阅读了这篇文章和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
就不再“占用”左边的空间了,它只是被对齐到左边(或西边),在它自己的空间块内。
解决布局问题通常有两种方法:
使用网格布局。这样可以很轻松地实现你想要的布局。网格布局可以解决大约95%的布局问题(想想看,这真的很厉害——Tk只用一个管理器就能做到,而大多数工具包需要好几个才能完成同样的事情!)
使用多个框架。如果有些组件需要上下排列,而有些需要左右排列,单靠一个框架可能无法满足所有需求。可以用一个框架来处理上下排列的部分,再用其他框架来处理左右排列的内容。
另外要明白,组件不一定要是它们被放置的框架的子组件。你可以使用“in”参数把组件放在其他容器中,而不是它们的父容器里。
举个例子,在你的具体情况中,你可以创建三个框架,分别是上、中、下。把这些框架在你的顶层窗口中上下排列。然后可以把第一个文本组件放在上框架,把按钮水平放在中框架,把另一个文本组件放在下框架。
这种方法的好处是将来更改布局会变得更简单(根据我的经验,这种情况总是会发生)。你不需要重新设置任何组件的父级,只需把它们放在其他容器中即可。
在你简单的例子中,可能没什么区别,但对于复杂的应用程序来说,这种策略可以省下很多麻烦。
我最好的建议是:布局不是随便想的事情。做一点规划,甚至可以花五分钟在图纸上画一下。首先决定你应用程序的主要区域,并为每个区域使用一个框架或其他容器(比如分隔窗口、笔记本等)。一旦确定了这些区域,就对每个部分采用相同的分而治之的方法。这样可以让你对应用程序的不同部分使用不同类型的布局。工具栏可以用水平布局,表单可以用垂直布局,等等。