2013-05-08 98 views
3

我需要理解模型/視圖/控制器方法背後的概念,以及如何以這種方式編寫GUI。這只是一個非常簡單的基本GUI。有人可以向我解釋如何使用MVC重寫這段代碼嗎?如何使用模型/視圖/控制器方法制作GUI?

from tkinter import * 

class Application(Frame): 
    """ GUI application that creates a story based on user input. """ 
    def __init__(self, master): 
     """ Initialize Frame. """ 
     super(Application, self).__init__(master) 
     self.grid() 
     self.create_widgets() 

    def create_widgets(self): 
     """ Create widgets to get story information and to display story. """ 
     # create instruction label 
     Label(self, 
       text = "Enter information for a new story" 
      ).grid(row = 0, column = 0, columnspan = 2, sticky = W) 

     # create a label and text entry for the name of a person 
     Label(self, 
       text = "Person: " 
      ).grid(row = 1, column = 0, sticky = W) 
     self.person_ent = Entry(self) 
     self.person_ent.grid(row = 1, column = 1, sticky = W) 

     # create a label and text entry for a plural noun 
     Label(self, 
       text = "Plural Noun:" 
      ).grid(row = 2, column = 0, sticky = W) 
     self.noun_ent = Entry(self) 
     self.noun_ent.grid(row = 2, column = 1, sticky = W) 

     # create a label and text entry for a verb 
     Label(self, 
       text = "Verb:" 
      ).grid(row = 3, column = 0, sticky = W) 
     self.verb_ent = Entry(self) 
     self.verb_ent.grid(row = 3, column = 1, sticky = W) 

     # create a label for adjectives check buttons 
     Label(self, 
       text = "Adjective(s):" 
      ).grid(row = 4, column = 0, sticky = W) 

     # create itchy check button 
     self.is_itchy = BooleanVar() 
     Checkbutton(self, 
        text = "itchy", 
        variable = self.is_itchy 
        ).grid(row = 4, column = 1, sticky = W) 

     # create joyous check button 
     self.is_joyous = BooleanVar() 
     Checkbutton(self, 
        text = "joyous", 
        variable = self.is_joyous 
        ).grid(row = 4, column = 2, sticky = W) 

     # create electric check button 
     self.is_electric = BooleanVar() 
     Checkbutton(self, 
        text = "electric", 
        variable = self.is_electric 
        ).grid(row = 4, column = 3, sticky = W) 

     # create a label for body parts radio buttons 
     Label(self, 
       text = "Body Part:" 
      ).grid(row = 5, column = 0, sticky = W) 

     # create variable for single, body part 
     self.body_part = StringVar() 
     self.body_part.set(None) 

     # create body part radio buttons 
     body_parts = ["bellybutton", "big toe", "medulla oblongata"] 
     column = 1 
     for part in body_parts: 
      Radiobutton(self, 
         text = part, 
         variable = self.body_part, 
         value = part 
         ).grid(row = 5, column = column, sticky = W) 
      column += 1 

     # create a submit button 
     Button(self, 
       text = "Click for story", 
       command = self.tell_story 
       ).grid(row = 6, column = 0, sticky = W) 

     self.story_txt = Text(self, width = 75, height = 10, wrap = WORD) 
     self.story_txt.grid(row = 7, column = 0, columnspan = 4) 

    def tell_story(self): 
     """ Fill text box with new story based on user input. """ 
     # get values from the GUI 
     person = self.person_ent.get() 
     noun = self.noun_ent.get() 
     verb = self.verb_ent.get() 
     adjectives = "" 
     if self.is_itchy.get(): 
      adjectives += "itchy, " 
     if self.is_joyous.get(): 
      adjectives += "joyous, " 
     if self.is_electric.get(): 
      adjectives += "electric, " 
     body_part = self.body_part.get() 

     # create the story 
     story = "The famous explorer " 
     story += person 
     story += " had nearly given up a life-long quest to find The Lost City of " 
     story += noun.title() 
     story += " when one day, the " 
     story += noun 
     story += " found " 
     story += person + ". " 
     story += "A strong, " 
     story += adjectives 
     story += "peculiar feeling overwhelmed the explorer. " 
     story += "After all this time, the quest was finally over. A tear came to " 
     story += person + "'s " 
     story += body_part + ". " 
     story += "And then, the " 
     story += noun 
     story += " promptly devoured " 
     story += person + ". " 
     story += "The moral of the story? Be careful what you " 
     story += verb 
     story += " for." 

     # display the story         
     self.story_txt.delete(0.0, END) 
     self.story_txt.insert(0.0, story) 

# main 
def main(): 
    root = Tk() 
    root.title("Mad Lib") 
    app = Application(root) 
    root.mainloop() 

main() 
+0

你的代碼只包含了「視圖」。它沒有模型和控制器。 – 2013-05-08 22:13:51

+0

@SimeonVisser - 好的,我該如何添加它們?我需要做什麼? – 2013-05-08 22:29:02

+0

@IvanLesiv:您需要一個稍微複雜一點的示例,在您的示例的MVC設計將對您做出任何意義或解釋任何事情之前,您實際上已經有一些對象或數據進行建模。 – abarnert 2013-05-08 22:31:04

回答

-4

如果你想開始/使用python語言學習MVC Web開發,我建議上手Django Framework

+4

他很清楚地試圖創建一個GUI應用程序來運行本地,而不是一個Web應用程序。 – abarnert 2013-05-08 22:26:16

6

ToyMVC「玩具MVC(模型 - 視圖 - 控制器)設計」在Tkinter的文檔可能就是你正在尋找。我個人設計的東西有點不同,但它大多是有道理的。

關鍵是分離出模型和視圖,然後控制器就是連接模型和視圖的所有位。

所以,而不是與它的一切的Application,你有這些類:

  • StoryModel:一個故事的模式。
  • StoryView:一個窗口或其他窗口小部件可以粘在窗體中 - 儘管在Tk中,您可以輕鬆地將窗體或框架自己製作。
  • StoryController:給定StoryModelStoryView的類將告訴其StoryView創建相應的小部件以顯示該故事,然後將監視Model和View以更改並將它們從一個傳送到另一個。

鑑於這種情況,你可以創建一個簡單Application創建一個StoryModel,一個StoryView,一個框架窗口放於視圖,一個StoryController連接起來的模型和視圖。

例如,StoryModel看起來是這樣的:

class StoryModel(object): 
    body_parts = ['bellybutton', 'big toe', 'medulla oblongato'] 
    def __init__(self): 
     self.person = ObservableStr('') 
     # ... 
     self.is_itchy = ObservableBool(False) 
     # ... 
    def tell(self): 
     story = "The famous explorer " 
     # ... 
     return story 

然後你就可以得到看中,並創建顯示以不同的方式在同一信息的AlternateStoryView,並改變Application創建每個觀點的一個,以及每個控制器,連接到相同的型號。例如,您可以創建並沒有使用網格視圖,而是自動佈置的事情了:

class AlternateStoryView(Frame): 
    def __init__(self, master): 
     super(StoryView, self).__init__(master) 
    def add_label(label): 
     label = Label(self, text=label) 
     label.pack() 
     return label 

如果你瞭解trace方法,你可能會注意到一個Observable是不是真的有什麼不同比使用Tkinter.StringVar,等等。但好處(除了沒有笨重的語法trace ...)是沒有什麼Tkinter - 這種方式的具體模型。

所以,你可以創建一個GtkStoryViewCursesStoryView,在不改變任何代碼的ModelController。 (這與ToyMVC不太一樣,因爲像addButton.config(command=self.addMoney)這樣的東西不會完全轉化爲Gtk +或者詛咒,除非你構建了一個大的Tk仿真層......但是你不必在你的設計中犯這個錯誤。)

另外,請注意,使用Observable包裝所有模型變量絕對不是連接控制器的唯一方法,甚至不一定是Pythonic。

+1

謝謝!這真的很有幫助! – 2013-05-09 00:47:31

+0

什麼是'ObservableStr'和'ObservableBool'?他們來自哪裏(代碼沒有進口,他們當然不是'tkinter')?這聽起來像是實現Tk到模型同步的重要模式,但我無法在任何地方找到它。 – 2018-02-22 17:44:49

相關問題