2013-05-08 68 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