[英]Tkinter Grid System: Arranging Elements
我目前正在編寫一個程序,該程序將與Discord的豐富功能配合使用,並且需要在Tkinter中為其創建GUI。 問題是,我不明白如何正確放置元素。 真是痛苦。 這是我計划使應用程序看起來像的樣子: https : //i.stack.imgur.com/K9Wox.jpg
但是,使用我當前的代碼,這就是GUI的外觀... https://i.stack.imgur.com/wGA9A.jpg
這是我的代碼:
root = tkinter.Tk()
root.title("Matter: A Discord Rich Presence Tool")
root.config(bg='#2C2F33')
root.geometry("560x300")
#root.overrideredirect(1)
# Load images
loadProfileImage = tkinter.PhotoImage(file="resources/loadprofile.png")
saveProfileImage = tkinter.PhotoImage(file="resources/saveprofile.png")
newProfileImage = tkinter.PhotoImage(file="resources/newprofile.png")
# GUI Hell starts here
topCanvas = tkinter.Canvas(root, width=600, height=150)
topCanvas.config(bd=0, highlightthickness=0, relief='ridge', background="#7289DA")
topTextFieldText = tkinter.StringVar(value='Sample top text')
topTextField = tkinter.Entry(root, textvariable=topTextFieldText)
topTextField.config(borderwidth=0, background="#7289DA")
bottomTextFieldText = tkinter.StringVar(value='Sample bottom text')
bottomTextField = tkinter.Entry(root, textvariable=bottomTextFieldText)
bottomTextField.config(borderwidth=0, background="#7289DA")
largeIconName = tkinter.StringVar()
largeIconNameField = tkinter.Entry(root, textvariable=largeIconName)
smallIconName = tkinter.StringVar()
smallIconNameField = tkinter.Entry(root, textvariable=smallIconName)
applicationIDFieldText = tkinter.StringVar()
applicationIDField = tkinter.Entry(root, textvariable=applicationIDFieldText)
applicationIDField.config(borderwidth=0, background="#23272A")
largeIconHoverText = tkinter.StringVar()
largeIconHoverTextField = tkinter.Entry(root, textvariable=largeIconHoverText)
largeIconHoverTextField.config(borderwidth=0, background="#23272A")
smallIconHoverText = tkinter.StringVar()
smallIconHoverTextField = tkinter.Entry(root, textvariable=smallIconHoverText)
smallIconHoverTextField.config(borderwidth=0, background="#23272A")
#greet_button = tkinter.Button(root, text="Run", command=run)
buttonFrame = tkinter.Frame(height=2, bd=0, relief=tkinter.SUNKEN)
newProfileButton = tkinter.Button(root, text="Save to profile", command=save)
newProfileButton.config(image=newProfileImage, borderwidth=0, background="#23272A")
saveButton = tkinter.Button(root, text="Save to profile", command=save)
saveButton.config(image=saveProfileImage, borderwidth=0, background="#23272A")
loadButton = tkinter.Button(root, command=load)
loadButton.config(image=loadProfileImage, borderwidth=0, background="#23272A")
# Grid stuff
topCanvas.grid(row=0, column=1)
applicationIDField.grid(row=3, column=1)
largeIconHoverTextField.grid(row=3, column=2)
smallIconHoverTextField.grid(row=3, column=3)
newProfileButton.grid(row=5, column=1, padx=(20, 5))
saveButton.grid(row=5, column=2, padx=(5, 5))
loadButton.grid(row=5, column=3, padx=(5, 20))
root.mainloop()
任何指導將不勝感激,因為我似乎無法弄清楚如何使用Tkinter的網格進行與上圖類似的布局。
首先,您必須向網格幾何管理器說明您希望畫布跨越所有三列:
topCanvas.grid(row=0, column=1, columnspan=3)
如果您未指定窗口小部件,則窗口小部件不會自動展開以填充整個列(或行);如果您未指定其sticky
位置,則窗口小部件將自動居中顯示在單元格中:
newProfileButton.grid(row=5, column=1, padx=(20, 5), sticky='w')
saveButton.grid(row=5, column=2, padx=(5, 5), sticky='w')
loadButton.grid(row=5, column=3, padx=(5, 20), sticky='w')
希望這會給您一些幫助,盡管還不能完全解決問題。
這是一個很好的教程: 第一次正確設置Tkinter網格大小
不要嘗試將所有內容放入單個網格中。 將您的UI分成幾個部分,然后為每個部分使用正確的工具。
我在您的UI中看到兩個主要部分:藍色的頂部具有一些信息,而底部的黑色背景具有一些按鈕。
因此,我將從在根窗口中創建這兩部分開始,並使用pack
將其中一個放在另一個之上:
topFrame = tk.Frame(root, background="#7289DA")
bottomFrame = tk.Frame(root, background="#2C2F33")
topFrame.pack(side="top", fill="both", expand=True)
bottomFrame.pack(side="bottom", fill="both", expand=True)
這樣,您現在將始終將根分為兩個彩色區域。 上面的代碼為它們提供了相等的大小。 您可以將一個或另一個的expand
值更改為False
,這取決於用戶調整窗口大小時要發生的情況。
不過,不要太擔心大小。 一旦您開始向每個部分添加小部件,它將改變。
底部似乎也分為兩個部分:一個用於輸入,另一個用於按鈕。 您可以在整個部分中使用單個網格布局,但是為了說明將UI划分為多個部分的概念,我們將底部分為兩部分。 另外,由於並非所有內容都整齊地排列在行和列中,所以這會使事情變得容易一些。
正如我之前提到的,您可能想在expand
選項中隨意擺弄,具體取決於您是希望這些框架在用戶調整窗口大小時是否相等地調整大小或保持相同的大小。
inputFrame = tk.Frame(bottomFrame, background="#2C2F33")
buttonFrame = tk.Frame(bottomFrame, background="#2C2F33")
inputFrame.pack(side="top", fill="both", expand=True)
buttonFrame.pack(side="top", fill="both", expand=True)
注意:如果您在此處停止並嘗試運行程序,則可能看不到這些框架。 在開發過程中,有時可以為它們提供獨特的顏色以幫助您可視化。 一旦一切正常,就可以將顏色調整為最終值。
現在,我們可以將條目小部件添加到底部的上半部分。 我們可以在這里使用grid
,因為所有內容都排列整齊。 重要的步驟是使行具有相等的權重,以便它們一起增長和收縮,不過您可以這樣做,以便根據需要僅調整一列的大小。
我還要指出,不需要使用StringVar
實例。 您可以,但是它添加了額外的對象以進行跟蹤,在大多數情況下,這是沒有必要的。
label1 = tk.Label(inputFrame, text="APPLICATION ID",
foreground="lightgray",
background="#2C2F33")
label2 = tk.Label(inputFrame, text="LARGE IMAGE HOVER",
foreground="lightgray",
background="#2C2F33")
label3 = tk.Label(inputFrame, text="SMALL IMAGE HOVER",
foreground="lightgray",
background="#2C2F33")
# columns should get extra space equally. Give any extra vertical space
# to an empty column below the entry widgets
inputFrame.grid_columnconfigure((0,1,2), weight=1)
inputFrame.grid_rowconfigure(2, weight=1)
appIdEntry = tk.Entry(inputFrame, borderwidth=0,
highlightthickness=0,
background="#23272A", bd=0)
largeImageEntry = tk.Entry(inputFrame,
highlightthickness=0,
background="#23272A", bd=0)
smallImageEntry = tk.Entry(inputFrame, borderwidth=0,
highlightthickness=0,
background="#23272A", bd=0)
label1.grid(row=0, column=0, sticky="w")
label2.grid(row=0, column=1, sticky="w", padx=10)
label3.grid(row=0, column=2, sticky="w")
appIdEntry.grid(row=1, column=0, sticky="ew")
largeImageEntry.grid(row=1, column=1, sticky="ew", padx=10)
smallImageEntry.grid(row=1, column=2, sticky="ew")
請注意,頂部似乎縮小了。 那只是因為它是空的。 Tkinter非常擅長於擴展和縮小內容以適合內部內容。 不用太擔心。 一旦一切正常,就可以進行調整。
我不想在此答案中重寫您的整個程序。 這里的要點是,您應該將您的UI分成邏輯塊,並使每個塊成為一個框架。 然后,您可以自由使用該框架中最有意義的任何幾何圖形管理器。 有時grid
是最好的,有時是pack
。 無論哪種情況,管理幾個高級框架都比將數十個小部件塞入單個網格要容易得多,尤其是在沒有清晰的行和/或列的情況下。
該解決方案還使為每個部分創建函數或類變得非常容易。 例如,您的主程序可能如下所示:
root = tkinter.Tk()
top = topSection(root)
bottom = bottomSection(root)
這樣,如果您決定完全重新設計UI的某個部分,則可以這樣做,而不必擔心會弄亂其他部分的布局,因為每個框架大多獨立於任何其他框架。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.