2013-02-13 57 views
4

我的投訴什麼是更好的Tkinter幾何經理比.grid()

我目前鑽研比「以往」前進入Tkinter的GUI深,我已經找到了.grid()幾何管理是不夠的幾個原因:

  1. 這些情節是基於其中最大的小部件 - 這種相對性導致不準確。

  2. 在Windows 7上的Python 2.7.3,該計劃似乎並沒有聽從我的行號,而是喜歡使用小工具的順序。

我的代碼

我目前工作的一個真的基本的文本編輯器,我想對框架的頂部多個按鈕。我一直無法這樣做,因爲我的部件放在要麼是占主導地位的屏幕中心的大規模文本框的最左邊或右邊。

========Class __init__ Stuff============ 
def widget(self):#Place widgets here 

    #Save Button 
    self.saveButton = Button (self, text = "Save", command = self.saveMe) 
    self.saveButton.grid(column = 0, row = 0, sticky = W) 

    #Open Button 
    self.openButton = Button (self, text = "Open", command = self.openMe) 
    self.openButton.grid(column = 0, row = 1, sticky = W) 
    #Area where you write 
    self.text = Text (self, width = (root.winfo_screenwidth() - 20), 
         height = (root.winfo_screenheight() - 10)) 
    self.text.grid(row = 2) 
==============Mainloop/Command Stuff============ 

我的問題

是否有另一種方式來使用.grid()幾何管理的方式,更準確的,或者我應該完全使用其他功能?

謝謝!

+0

你對windows的評論不是「heeding your row numbers」是不正確的。幾十年來,網格幾何管理器已被證明在所有平臺上都可以100%運行。我並不是說你的代碼不是行爲不端,這只是因爲你認爲它的原因而不是行爲不端。 – 2013-02-13 12:07:35

回答

14

有3個幾何管理器,您可以使用 - grid,packplace。第三種是最一般的,但也很難使用。我更喜歡grid。請注意,您可以將部件等部件的內部 - 或者你可以指定columnspan。所以,如果你想獲得以下佈局:

------------------------- 
    | Button1 | Button2 | 
    ------------------------- 
    |  Big Widget  | 
    ------------------------- 

有2種規範的方式使用.grid做到這一點。第一種方法是columnspan

import Tkinter as Tk 
root = Tk.Tk() 
b1 = Tk.Button(root,text="Button1") 
b1.grid(row=0,column=0) 
b2 = Tk.Button(root,text="Button2") 
b2.grid(row=0,column=1) 
big_widget = Tk.Canvas(root) 
big_widget.grid(row=1,column=0,columnspan=2) 

*請注意,有一個完全類似rowspan選項也是如此。

第二種方法是使用Frame牽你的按鈕:

import Tkinter as Tk 
root = Tk.Tk() 
f = Tk.Frame(root) 
f.grid(row=0,column=0) 
#place buttons on the *frame* 
b1 = Tk.Button(f,text="Button1") 
b1.grid(row=0,column=0) 
b2 = Tk.Button(f,text="Button2") 
b2.grid(row=0,column=1) 

big_widget = Tk.Canvas(root) 
big_widget.grid(row=1,column=0) #don't need columnspan any more. 

此方法用於創建複雜的佈局SUPER有用的 - 我不知道你怎麼會不創建一個複雜的佈局使用Frame對象是這樣的...

+0

好的....所以你使用Tk.Canvas而不是Tk.Text,對嗎?另外,如何使用.place()以及爲什麼它是最普通/準確的(含義不明確)(我的意思是模糊的) – xxmbabanexx 2013-02-13 03:59:19

+0

,使用'.place',您指定了要放置該小部件的確切座標。就我而言,那將是一場維護**噩夢**,而且幾乎不值一提。 - 是的,我說'畫布'而不是'文本' - 我只需要選擇一個通常比'Button'小部件所需空間大得多的部件;-) – mgilson 2013-02-13 04:00:39

+0

+1 - 根據我的經驗許多不同的GUI工具包和幾何管理器,使用一個非常簡單的佈局管理器,並將不同的組嵌套到目前爲止最好。所有那些更復雜的幾何圖形(我說的是Swing和所有不同的管理者)都很難使用,並且沒有給你任何你無法用嵌套方法得到的東西。 – Voo 2013-02-13 04:06:18

5

「最好」的幾何經理取決於你想要做什麼,沒有幾何經理是最適合所有情況。對於你在這個特定情況下要做的事情,包可能是更好的選擇。另請注意,應用程序中可能有多個「最佳」。在應用程序的不同部分使用網格和包是很正常的。我很少創建一個GUI,我不使用網格和包。很少,我也使用地方。

pack擅長將東西放在單行和單列中。例如,工具欄是使用包的最佳例子,因爲您希望所有按鈕都對齊到左側。正如其名稱所暗示的,當您想要固定的行和列時,最好使用網格。在網格和包裝都不會做的罕見情況下,地點很有用,因爲它允許您將小部件放置在精確的固定位置或相對位置。

我的建議是將您的應用程序窗口小部件分成組,併爲每個組使用正確的幾何管理器。在你的情況下,你有兩個邏輯組:頂部的工具欄和底部的文本部件和滾動條組合。所以,從兩個幀開始。由於工具欄位於頂部,文本小部件位於下方,所以包裝效果最佳。

toolbar = tk.Frame(...) 
main = tk.Frame(...) 
toolbar.pack(side="top", fill="x", expand=False) 
main.pack(side="bottom", fill="both", expand=True) 

上面給出了兩個易於獨立修改的區域。

對於工具欄,包裝再次是最自然的。但是,在這種情況下,您需要沿着左側而不是沿着頂部或底部的按鈕:

b1 = tk.Button(toolbar, ...) 
b2 = tk.Button(toolbar, ...) 
b1.pack(side="left") 
b2.pack(side="left") 
... 

最後,底部區域。您的示例代碼不顯示滾動條,但我認爲在某些時候您會想要添加它們。如果您同時使用水平和垂直滾動條,則網格運行良好。我會放下它們像這樣:

hsb = tk.Scrollbar(main, ..., orient="horizontal", ...) 
vsb = tk.Scrollbar(main, ..., orient="vertical", ...) 
text = tk.Text(main, ...) 
vsb.grid(row=0, column=1, sticky="ns") 
hsb.grid(row=1, column=0, sticky="ew") 
text.grid(row=0, column=0, sticky="nsew") 
main.grid_rowconfigure(0, weight=1) 
main.grid_columnconfigure(0, weight=1) 

這最後一部分是很重要的 - 你總是需要給一個權重至少一行和一列。這會告訴網格窗口調整大小時哪些行和列應該增長和縮小。

0

我找到place經理最直觀,最準確的所有三個,因爲對於兩個位置和大小指定的絕對和相對長度組合的可能性:

mywidget.place(x=..., y=..., width=..., height=...) # absolute 
mywidget.place(relx=..., rely=..., relwidth=..., relheight=...) # relative 

# combination 
pad_left=5 
pad_right=5 
pad_top=5 
pad_bottom=5 
mywidget.place(relx=0, x=pad_left, rely=0, y=pad_top,\ 
     relwidth=1, width=-pad_left-pad_right,\ 
     relheight=1, height=-pad_top-pad_bottom, anchor="e") # use the whole space except some padding 

出於某種原因,.place經理看起來並不是很受歡迎,但是我發現定義你的小部件應該在父窗口調整大小時應該如何四處移動並調整其大小,這是非常好的工作。

爲了減輕複雜窗口的建設,我有時用一個功能(一種模擬網格的行爲我想)在垂直放置,以幫助,比如:

def offset_y(line_no): 
    if line_no == 0: 
     return 0 
    else: 
     return height_label + (line_no - 1)*height_button 

mylabel.place(..., y=offset_y(0)) 
mybtn1.place(..., y=offset_y(1)) 
etc. 

垂直收拾標籤然後是一系列按鈕。 (當然,在這種情況下可以使用.pack管理器,但我更喜歡.place管理器的原因是爲了更準確地理解窗口大小調整時的情況。

+0

我不明白你對準確性的評論。例如,當我使用包和網格時,我確切知道他們將如何表現。在這方面如何更準確?至於爲什麼大多數人不使用場所,這可能是因爲它更復雜:它需要你自己做很多數學。包和網格都爲您處理大部分數學問題。 – 2013-04-06 15:52:09

+1

我想我喜歡'place'就是座標系。 @Bryan Oakley:在這個意義上說是準確的:我確切地知道我在哪裏放置我的小部件,以及我在框架內以絕對座標或相對座標給出它的大小。我可以像這樣添加我的所有小部件。我不特別喜歡關於'pack'的東西,就是需要一個不可見的'Frame'層次結構來對小部件進行分組。我不特別喜歡'grid',當窗口大小調整應該移動窗口部件但不修改窗口大小時,必須使用'buffer'(不可見)行/列來提供可擴展'填充'。但是也許我錯過了某事? – 2013-04-07 16:15:13

-2

而不是行,列....等,您可以使用座標。

它可能比其他人更容易。

例:

from Tkinter import* 
root=Tk() 
Button(root,text="HI").grid(padx=100,pady=50) 
root.mainloop() 

通過改變padx和pady值試試吧youself。

相關問題