12

我正在尝试编写一个基本的 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

4 回答 4

17

布局问题一般有两种解决方案:

  1. 切换到使用网格。像你想要完成的那样做布局变得非常容易。Grid 可以解决大约 95% 的布局问题(想想就觉得不可思议——Tk 只需一个管理器就可以完成大多数工具包需要六个才能完成的工作!)

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

还要意识到小部件不必是它们被打包/网格化的小部件的子级。您可以使用“in”参数将小部件放在其他容器中而不是它们的父容器中。

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

这种方法的优点是它使将来更改布局变得更加容易(根据我的经验,这总是在某个时候发生)。您不必重新设置任何小部件的父级,只需将它们打包/放置/网格在其他容器中。

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

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

于 2009-09-29T11:40:58.333 回答
9

我最初误解了包装的工作原理,并没有意识到当我这样做时整个左侧都被“认领”了x.pack(side=LEFT)。在阅读内容和亚历克斯在这里的回答后,我发现我并没有真正x打包到左侧,而是将其固定在左侧,使用anchor=W(W for West) 而不是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不再“声称”左侧,它只是在其空间块内与左侧(或西部)对齐。

于 2009-09-28T06:22:03.283 回答
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 在获得焦点之前不会清楚地显示文本,但按钮非常清晰;-)。

于 2009-09-28T05:15:17.410 回答
3

与 WebView 使用 Mosaic Canvas Widget Sets internals(与 Tk 非常相似)的方式相同。诀窍是第二个相同名称的框架对象作为块级浮点(内联:块;)用于放置在它之后的所有内容,并且已经调用“fr”的所有内容都将在其中自动重新开始。

你可以有很多这样做的 TOP 对齐的小部件,只需添加另一个相同的名为 Frame 的地方,你想在 side=LEFT 之间打破。也可以在底部之后工作。

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.
于 2019-03-29T06:49:11.747 回答