繁体   English   中英

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

[英]How to pack a tkinter widget underneath an existing widget that has been packed to the left side?

我正在尝试编写一个基本的 Tkinter GUI,它的顶部有一个Text小部件,然后一个Button小部件在其下方左对齐,然后是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小部件,使其出现在按钮下方,而不是它的右侧?

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

  1. 切换到使用网格。 像您想要完成的那样进行布局变得非常容易。 Grid 可以解决大约 95% 的所有布局问题(当您想到它时,这真是太神奇了——Tk 只需一个经理就可以完成大多数工具包需要六个才能完成的工作!)

  2. 使用多个框架。 如果某些小部件需要从上到下堆叠,而一些小部件需要从左到右堆叠,那么您无法总是获得想要的东西,将所有东西都打包到一个框架中。 布局的从上到下部分使用一个框架,从左到右的内容使用附加框架。

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

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

这种方法的优点是它可以更轻松地在将来更改布局(根据我的经验,这种情况总是在某些时候发生)。 您不必重新设置任何小部件的父级,只需将它们打包/放置/网格放在其他容器中即可。

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

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

我最初误解了包装是如何工作的,并且没有意识到当我执行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不再“声称”左侧,它只是在其空间块内与左侧(或西部)对齐。

打包是按照 .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()

(将 Texts 更改为 Buttons 仅用于更直接的布局可见性-此 Mac 上的 Tkinter 在获得焦点之前不会清楚地显示 Texts,但 Buttons 非常清晰;-)。

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

您可以让许多 TOP 对齐的小部件执行此操作,只需添加另一个相同的命名框架,您希望在 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.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM