2013-05-01 56 views
2

甚至可以在Tkinter中設置網格的絕對位置嗎?我正在嘗試創建一個類似於下圖的GUI,但我可能會以錯誤的方式進行操作。所以如果可能的話,你如何設置網格位置?如何使用Tkinter設置網格的位置?

目標GUI:

Target GUI

這是我的GUI是如何轉向了,至今:

My GUI

正如你看到的,我的新聯繫人必須在對,而聯繫人列表應該在左邊。我知道如何使用絕對值來移動聯繫人列表,但我可以對我的網格元素執行相同的操作嗎?或者我應該使用所有這些絕對值,並結合填充?

目前,這是我的代碼:

from tkinter import * 
contacts=['Justin Day'] 

class Contact_manager (Frame): 

    def __init__(self, parent): 
     Frame.__init__(self, parent) 

     self.parent = parent 
     self.initUI() 

    def initUI(self): 
     self.parent.title("Contact Manager") 
     self.pack(fill=BOTH, expand=1) 

     #New contact grid 
     Label (self, text = "New Contact").grid (row=0, columnspan=2) 
     Label (self, text = "First Name:").grid (row=1, sticky=E) 
     Label (self, text = "Last Name:").grid (row=2, sticky=E) 
     Label (self, text = "Phone#").grid (row=3, sticky=E) 

     self.entry1 = Entry(self) 
     self.entry2 = Entry(self) 
     self.entry3 = Entry(self) 
     self.entry1.grid (row=1, column=1) 
     self.entry2.grid (row=2, column=1) 
     self.entry3.grid (row=3, column=1) 

     friend_check = IntVar() 
     self.friend_check = Checkbutton (self, variable = friend_check, 
           command = self.friend_box, 
           text = "Friend") 
     self.friend_check.grid (row=4, columnspan=2) 

     Label (self, text = "Email:").grid (row=5, sticky=E) 
     Label (self, text = "Birthday:").grid (row=6, sticky=E) 

     self.entry4 = Entry(self) 
     self.entry5 = Entry(self) 
     self.entry4.grid (row=5, column=1) 
     self.entry5.grid (row=6, column=1) 

     #Contact listbox 
     Label (self, text = "Contact List").place(x=20, y=190) 
     contact_lb = Listbox(self) 
     for i in contacts: 
      contact_lb.insert(END, i) 

     contact_lb.bind("<<ListboxSelect>>", self.onSelect) 
     contact_lb.place(x=20, y=210) 

    def onSelect(self, val): 

     sender = val.widget 
     idk = sender.curselection() 
     value = sender.get(idx) 

     self.var.set(value) 

    def friend_box(): 
     if friend_check.get() == 1: 
      contacts.append(Friend(f, l, p, e, bd)) 
     else: 
      contacts.append(Person(f, l, p)) 
def main(): 

    root = Tk() 
    ex = Contact_manager(root) 
    root.geometry('600x700+200+100') 
    root.mainloop() 

if __name__ == '__main__': 
    main() 

回答

5

你應該採取在GUI中佈置小部件的分而治之的方法。不要試圖一次做所有事情,或者使用一個幾何管理器在一個窗口中協調一切。要有條不紊,一次解決一個小問題。

例如,在您的目標GUI中,看起來您有四個部分:聯繫人列表,搜索框和按鈕,新聯繫人表單以及右下角(搜索結果?)中的內容。如果我認爲這些是四個不同的領域,那麼首先創建四個框架。使用網格將它們放置在主窗口的四個角落。給每個框架一個不同的顏色(用於調試目的)。現在,擺弄這些選項,直到這四個區域以您想要的方式增長和縮小。確保你給列和行的權重,以便他們都適當調整大小。

現在你已經做到了,你有四個更小,更易於管理的佈局問題。現在,這可能是我錯了 - 也許你有兩個區域,左側和右側。或者,也許你有三個 - 左邊,然後右上和右下。現在我們假設我是對的,但技術保持不變。

看起來你已經有了聯繫表單的佈局,所以把它們移到右上角的框架中。確保當你長大和縮小窗口時,它們都能正確展開和收縮(因此,你可以增長和縮小包含的框架)。

一旦你完成了,在下一部分工作 - 把聯繫人列表在左上角。再次確保它全部調整正確。此時,您不必擔心右側的小部件,因爲您已經完成了這些小部件。對於本節你不需要grid,你可以使用pack,因爲它只是堆疊在一起的幾個小部件。但是,您可以使用最合理的方式。

繼續這種方式,在GUI的剩餘兩個角上工作。有條不紊,一次處理一個小的獨立部分。

+1

謝謝!我喜歡你如何解釋這些方法去做事情,以便我能夠理解如何徹底打破它。創建多個框架時,創建每個框架作爲方法還是作爲單獨的類創建更好?哪種更加Pythonic?謝謝。 – 2013-05-01 18:18:39

2

下面是一些看起來更接近你所需要的:

from tkinter import * 
contacts=['Justin Day'] 

class Contact_manager (Frame): 

    def __init__(self, parent): 
     Frame.__init__(self, parent) 

     self.parent = parent 
     self.initUI() 

    def initUI(self): 
     self.parent.title("Contact Manager") 
     self.pack(fill=BOTH, expand=1) 

     #New contact grid 
     Label (self, text = "New Contact").grid (row=0, column=2, columnspan=2, sticky=W) 
     Label (self, text = "First Name:").grid (row=1, column=1, sticky=E) 
     Label (self, text = "Last Name:").grid (row=2, column=1, sticky=E) 
     Label (self, text = "Phone#").grid (row=3, column=1, sticky=E) 

     self.entry1 = Entry(self) 
     self.entry2 = Entry(self) 
     self.entry3 = Entry(self) 
     self.entry1.grid (row=1, column=2) 
     self.entry2.grid (row=2, column=2) 
     self.entry3.grid (row=3, column=2) 

     friend_check = IntVar() 
     self.friend_check = Checkbutton (self, variable = friend_check, 
           command = self.friend_box, 
           text = "Friend") 
     self.friend_check.grid (row=4, column=2, columnspan=2) 

     Label (self, text = "Email:").grid (row=5, column=1, sticky=E) 
     Label (self, text = "Birthday:").grid (row=6, column=1, sticky=E) 

     self.entry4 = Entry(self) 
     self.entry5 = Entry(self) 
     self.entry4.grid (row=5, column=2) 
     self.entry5.grid (row=6, column=2) 

     #Contact listbox 
     Label (self, text = "Contact List").grid(row=0) 
     contact_lb = Listbox(self) 
     for i in contacts: 
      contact_lb.insert(END, i) 

     contact_lb.bind("<<ListboxSelect>>", self.onSelect) 
     contact_lb.grid(row=1, rowspan=5) 

    def onSelect(self, val): 

     sender = val.widget 
     idk = sender.curselection() 
     value = sender.get(idx) 

     self.var.set(value) 

    def friend_box(): 
     if friend_check.get() == 1: 
      contacts.append(Friend(f, l, p, e, bd)) 
     else: 
      contacts.append(Person(f, l, p)) 
def main(): 

    root = Tk() 
    ex = Contact_manager(root) 
    root.geometry('600x700+200+100') 
    root.mainloop() 

if __name__ == '__main__': 
    main() 

我不知道你是否應該混合.grid()和.place(),據我所知,你不應該混合使用.pack()和.grid()。無論如何,我會盡量不要混合其中的任何一個。

而關於主要問題「你怎麼設置網格的位置」,那麼,就試着畫出你期望在紙上的東西,並試圖將其分爲行和列...

+1

你永遠不應該在同一個容器中混合電網和包裝,但它是相當正常的在同一應用程序同時使用。使用地方相當不尋常。 – 2013-05-01 11:08:15

2

我沒有類似的東西,檢查出來:

from Tkinter import Tk, N, S, W, E, BOTH, Text, Frame,Label, Button,Checkbutton, IntVar,Entry 


class Example(Frame): 

    def __init__(self, parent): 
     Frame.__init__(self, parent) 
     self.parent = parent 
     self.initUI() 

    def initUI(self):  
     self.parent.title("Windows") 


     Label(text="Contact List").grid(row=0,column=0,columnspan=2) 
     Text(width=30,height=15).grid(row=1,rowspan=9, column=0,columnspan=2,padx=20) 
     Button(text="Display Contact").grid(row=10, column=0,columnspan=2,pady=10) 
     Label(text="Last Name:").grid(row=11, column=0,pady=10) 
     Entry().grid(row=11,column=1) 
     Button(text="Search").grid(row=12,column=0,columnspan=2) 



     Label(text="New Contact").grid(row=0,column=2,columnspan=2) 
     Label(text="First Name:").grid(row=1,column=2,sticky=E) 
     Entry().grid(row=1,column=3) 
     Label(text="Last Name:").grid(row=2,column=2,sticky=E) 
     Entry().grid(row=2,column=3) 
     Label(text="Phone #:").grid(row=3,column=2,sticky=E) 
     Entry().grid(row=3,column=3) 
     friend_check = IntVar() 
     Checkbutton(variable=friend_check, command = self.friend_box, text = "Friend").grid(row=4,column=3,sticky=W) 
     #Label(text="Friend").grid(row=4,column=3,padx=20,sticky=W) 
     Label(text="Email:").grid(row=5,column=2,sticky=E) 
     Entry().grid(row=5,column=3) 
     Label(text="Birthday:").grid(row=6,column=2,sticky=E) 
     Entry().grid(row=6,column=3) 
     Button(text="Add Contact").grid(row=7,column=3,sticky=E) 

    def friend_box(self): 
     if friend_check.get() == 1: 
      print '1' 
     else: 
      print '0' 


def main(): 

    root = Tk() 
    root.geometry("600x450+900+300") 
    root.resizable(0,0) 
    app = Example(root) 
    root.mainloop() 


if __name__ == '__main__': 
    main()