[英]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
小部件,使其出現在按鈕下方,而不是它的右側?
布局問題一般有兩種解決方案:
切換到使用網格。 像您想要完成的那樣進行布局變得非常容易。 Grid 可以解決大約 95% 的所有布局問題(當您想到它時,這真是太神奇了——Tk 只需一個經理就可以完成大多數工具包需要六個才能完成的工作!)
使用多個框架。 如果某些小部件需要從上到下堆疊,而一些小部件需要從左到右堆疊,那么您無法總是獲得想要的東西,將所有東西都打包到一個框架中。 布局的從上到下部分使用一個框架,從左到右的內容使用附加框架。
還要意識到小部件不必是它們被打包/網格化的小部件的子部件。 您可以使用“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.