2016-10-19 24 views
0

我一直嘗試OOP與Tkinter的使用 - 林到達那裏(我認爲),緩慢...的Tkinter類結構(每幀類)問題與複製部件

我想建立一個結構,其中每個幀由其自己的類處理,包括它的所有小部件和功能。也許我來自錯誤的角度,但這對我來說最合乎邏輯。 - 隨時告訴我,如果你同意/不同意!

我知道問題出現的原因 - 即時呼叫每個班級時,我的__init__每次都運行並構建相關的小部件,無論它們是否已存在於框架中。但是,我能想到繞過這一點的唯一方法就是在我的主類GUI_Start__init__中構建每個幀。 - 雖然這似乎是一個混亂和無組織的解決問題。

有沒有一種方法可以實現一個結構,其中每個類都照顧它自己的函數和小部件,但不會每次構建框架?

請參閱以下問題的小例子:

from Tkinter import * 

class GUI_Start: 

    def __init__(self, master): 
     self.master = master 
     self.master.geometry('300x300') 
     self.master.grid_rowconfigure(0, weight=1) 
     self.master.grid_columnconfigure(0, weight=1) 
     self.win_colour = '#D2B48C' 
     self.frames = {} 

     for window in ['win1', 'win2']: 
      frame = Frame(self.master, bg=self.win_colour, bd=10, relief=GROOVE) 
      frame.grid(row=0, column=0, sticky='news') 
      setattr(self, window, frame) 
      self.frames[window] = frame 

     Page_1(self.frames) 

    def Next_Page(self, frames, controller): 
     controller(frames) 


class Page_1(GUI_Start): 

    def __init__(self, master): 
     self.master = master 
     self.master['win1'].tkraise() 

     page1_label = Label(self.master['win1'], text='PAGE 1') 
     page1_label.pack(fill=X) 

     page1_button = Button(self.master['win1'], text='Visit Page 2...', command=lambda: self.Next_Page(self.master, Page_2)) 
     page1_button.pack(fill=X, side=BOTTOM) 


class Page_2(GUI_Start): 

    def __init__(self, master): 
     self.master = master 
     self.master['win2'].tkraise() 

     page2_label = Label(self.master['win2'], text='PAGE 2') 
     page2_label.pack(fill=X) 

     page2_button = Button(self.master['win2'], text='Back to Page 1...', command=lambda: self.Next_Page(self.master, Page_1)) 
     page2_button.pack(fill=X, side=BOTTOM) 


root = Tk() 
gui = GUI_Start(root) 
root.mainloop() 

隨意批判結構,我可能會嘗試從錯誤的角度接近這個!

任何反饋將不勝感激! Luke

+0

您最初複製的代碼是否正確的方式。每個「頁面」應該從「Frame」繼承,並且頁面中的所有小部件都進入該幀。你想通過不同的方式完成什麼?請參閱http://stackoverflow.com/a/7557028/7432 –

+0

不確定您最初複製的代碼是什麼意思!你的例子中的幾個問題 - 它看起來像你創建一個框架來包含其他框架,因爲我創建框架和網格在根。你有這樣的理由嗎?或者我應該怎麼做?另外,你可以擴展你爲什麼在每個類中都有雙重__init__嗎? –

+0

爲什麼它的價值,我沒有複製任何代碼:) –

回答

1

使用類的要點是將一堆行爲封裝爲一個單元。一個對象不應該修改它自身以外的任何東西。至少,不是簡單地創建對象 - 你可以有可能產生副作用的方法。

在我看來,創建「頁面」的正確方法是從Frame繼承。所有屬於「頁面」的小部件都必須具有該對象本身作爲其父項。例如:

class PageOne(tk.Frame): 
    def __init__(self, parent): 
     # use the __init__ of the superclass to create the actual frame 
     tk.Frame.__init__(self, parent) 

     # all other widgets use self (or some descendant of self) 
     # as their parent 

     self.label = tk.Label(self, ...) 
     self.button = tk.Button(self, ...) 
     ... 

一旦這樣做,你可以把這個類的實例,好像他們是一個Widget:

root = tk.Tk() 
page1 = PageOne(root) 
page1.pack(fill="both", expand=True) 

你也可以創建一個基Page類,並有實際的網頁繼承從它,如果你的所有網頁有共同點(例如,一個頁眉或頁腳)

class Page(tk.Frame): 
    def __init__(self, parent): 
     tk.Frame.__init__(self, parent) 
     <code common to all pages goes here> 

class PageOne(Page): 
    def __init__(self, parent): 
     # initialize the parent class 
     Page.__init__(self, parent) 

     <code unique to page one goes here> 
+0

有了這個結構,我將如何配置窗口的基本尺寸(幾何)?感謝您的回答 –

+1

您可以爲主窗口創建一個單獨的類,並從'Tk'繼承。或者,從'object'繼承,並簡單地將根窗口作爲它的一個屬性。重點在於,對象不應直接影響本身以外的任何內容。 –

1

您在這裏使用OOP並不是很合乎邏輯。你的主程序在類GUI_start中。如果您的頁面從GUI_start繼承,那麼基本上您會爲每個創建的頁面實例創建一個全新的程序。你應該繼承Frame,就像Bryan Oakley在評論中指出的那樣。以下是您發佈內容的某種修復版本。布賴恩原來的那個還是好多了。

from Tkinter import * 

class GUI_Start: 

    def __init__(self, master): 
     self.master = master 
     self.master.geometry('300x300') 
     self.master.grid_rowconfigure(0, weight=1) 
     self.master.grid_columnconfigure(0, weight=1) 
     self.win_colour = '#D2B48C' 
     self.current_page=0 

     self.pages = [] 
     for i in range(5): 
      page = Page(self.master,i+1) 
      page.grid(row=0,column=0,sticky='nsew') 
      self.pages.append(page) 

     for i in range(2): 
      page = Page_diff(self.master,i+1) 
      page.grid(row=0,column=0,sticky='nsew') 
      self.pages.append(page) 

     self.pages[0].tkraise() 

     def Next_Page(): 
      next_page_index = self.current_page+1 
      if next_page_index >= len(self.pages): 
       next_page_index = 0 
      print(next_page_index) 
      self.pages[next_page_index].tkraise() 
      self.current_page = next_page_index 

     page1_button = Button(self.master, text='Visit next Page',command = Next_Page) 
     page1_button.grid(row=1,column=0) 



class Page(Frame): 

    def __init__(self,master,number): 
     super().__init__(master,bg='#D2B48C') 
     self.master = master 
     self.master.tkraise() 

     page1_label = Label(self, text='PAGE '+str(number)) 
     page1_label.pack(fill=X,expand=True) 



class Page_diff(Frame): 

    def __init__(self,master,number): 
     super().__init__(master) 
     self.master = master 
     self.master.tkraise() 

     page1_label = Label(self, text='I am different PAGE '+str(number)) 
     page1_label.pack(fill=X) 



root = Tk() 
gui = GUI_Start(root) 
root.mainloop() 
+0

感謝您的反饋@Jannick! –