我需要理解模型/视图/控制器方法背后的概念以及如何以这种方式编写GUI。这里只是一个非常基本的简单GUI。有人可以向我解释如何使用MVC重写此代码吗?
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 :(得分:7)
ToyMVC Tkinter文档中的“玩具MVC(模型视图控制器)设计”可能正是您所寻找的。我个人会设计一些不同的东西,但它最有意义。
关键是将模型和视图分开,然后控制器就是连接模型和视图的所有位。
所以,不是让Application
包含其中的所有内容,而是拥有这些类:
StoryModel
:一个故事模型。StoryView
:你坚持在框架内的窗口或其他小部件 - 虽然在Tk中,你可以很容易地将它作为框架本身。StoryController
:给定StoryModel
和StoryView
的类会告诉其StoryView
创建适当的小部件来显示该故事,然后监控模型和视图都已更改,并将它们从一个传输到另一个。鉴于此,您可以创建一个简单Application
创建一个StoryModel
,一个StoryView
,一个框架窗口放入View,一个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
- 这种方式具体的模型。
因此,您可以创建GtkStoryView
或CursesStoryView
,而无需更改Model
和Controller
中的任何代码。 (这与ToyMVC不太一致,因为addButton.config(command=self.addMoney)
之类的东西不会完全转换为Gtk +或curses,除非你构建了一个大的Tk仿真层......但你不必在你的设计中犯这个错误。 )
另外,请注意,在所有模型变量周围使用Observable
包装器绝对不是连接控制器的唯一方法,甚至也不一定是最Pythonic。
答案 1 :(得分:-4)
如果您想使用python语言开始/学习MVC Web开发,我建议您开始使用Django Framework