MVC架构模式在Tkinter中的运用

来源:互联网 发布:查看本机端口是否打开 编辑:程序博客网 时间:2024/05/16 15:04

      最近买了一本《精通Python设计模式》(作者:Sakis Kasampails),其中有一章是关于MVC的。MVC作为一种非常经典而且基础的架构模式,非常值得学习。

      最近,随着深度学习的研究,我整个技术开发使用的语言基本上转向Python了,所以最近看了《Introduction to Programming Using Python》,其中有一章是GUI编程,使用的Tkinter,虽然其介绍较为基础,并不是完整的API介绍,但大部分常用的功能均有涉及。

      然而,在使用Tkinter编写GUI程序,并且功能比较多的时候,我们的代码往往显得杂乱无章。因此,需要一个良好的设计模式来进行代码的管理,所以我选择了MVC模式来进行尝试。

      本文的结构如下:大致分为三个部分。第一部分讲解MVC模式的含义。第二部分讲解了《精通Python设计模式》一书中关于MVC的示例,该示例清晰地展示了MVC架构模式的精髓,从头构建了一个MVC模式的控制台程序。第三部分我将介绍该示例的GUI版本,使用Tkinter工具以及MVC模式进行实现。


      第一部分:什么是MVC架构模式?

模型-视图-控制器(Model-View-Controller,MVC)模式,其名称来自用来切分软件应用的三个主要部分:模型、视图、控制器。

      模型是核心的部分,代表这应用的信息本源,包含和管理(业务)逻辑、数据、状态以及应用的规则。视图是模型的可视化表现(比如:计算机图形用户界面、控制台界面、智能手机的应用图形界面、PDF文档、饼图和柱状图等。视图只是展示数据,并不处理数据。控制器是模型与视图之间的胶水(glue)。模型与视图之间的所有通信都通过控制器进行。

      我觉得链接http://www.itpub.net/thread-1869988-1-1.html的MVC示意图对帮助理解MVC有一定的帮助,如下图所示:


      图中,用户向控制器提出一些操作请求,然后控制器将这些请求传到模型层进行处理,模型层处理完毕之后会将结果返回给控制器,控制器将结果更新到视图上给用户一个视觉上的反馈。

      看了上述的解释以及示意图,想必你还是不能完全理解MVC模式,那下面进入第二部分,通过介绍一个示例来进一步感受MVC的设计思想。


      第二部分:MVC控制台示例讲解

      

'''这是一个简单的示例,用来展示如何从头实现MVC。示例名称:名人名言打印机想法:用户输入一个数字,然后就能看到与这个数字相关的名人名言。    名人名言存储在一个quotes元组中。    这种数据通常存放在数据库、文件或其他地方,只有模型能够直接访问它。'''quotes = ('A man is not complete until he is married.Then he is finished.',          'As I said before,I never repeat myself.',          'Behind a successful man is an exhausted woman.',          'Black holes really suck...', 'Facts are stubborn things.')# 模型极为简约,只有一个get_quote()方法,基于索引n从quotes元组中返回对于的名人名言。class QuoteModel:    def get_quote(self, n):        try:            value = quotes[n]        except IndexError as err:            value = 'Not found!'        return value# 视图有3个方法,分别是show(),error(),select_quote()# show()用于在屏幕上输出一句名人名言(或者提示Not found)# error()用于在屏幕上输出一条错误信息# select_quote()用于读取用户的选择class QuoteTerminalView:    def show(self, quote):        print('And the quote is:"{}"'.format(quote))    def error(self, msg):        print('Error:{}'.format(msg))    def select_quote(self):        return input('Which quote number would you like to see? ')#控制器负责协调。#__init__()方法初始化模型和视图#run()方法校验用户提供的名言索引,然后从模型中获取名言,并返回给视图class QuoteTerminalController:    def __init__(self):        self.model=QuoteModel()        self.view=QuoteTerminalView()    def run(self):        valid_input=False        while not valid_input:            n=self.view.select_quote()            try:                n=int(n)            except ValueError as err:                self.view.error("Incorrect index '{}'".format(n))            else:                valid_input=True        quote=self.model.get_quote(n)        self.view.show(quote)def main():    controller=QuoteTerminalController()    while True:        controller.run()main()

      第三部分:Tkinter MVC实践

import tkinter as tkquotes = ('A man is not complete until he is married.Then he is finished.',          'As I said before,I never repeat myself.',          'Behind a successful man is an exhausted woman.',          'Black holes really suck...', 'Facts are stubborn things.')class QuoteModel:    def get_quote(self, n):        try:            value = quotes[n]        except IndexError as err:            value = 'Not found!'        return valueclass QuoteGUIView:    def __init__(self):        self.window = tk.Tk()        self.window.title("名人名言选择器")        frame1 = tk.Frame(self.window)        frame1.pack()        tk.Label(frame1, text="请输入需要查找的名言的索引? ").pack(side="left")        self.quoteNum = tk.StringVar()  # 名言索引        tk.Entry(frame1, textvariable=self.quoteNum, justify="right").pack(side="left")        self.btn = tk.Button(frame1, text="查询")        self.btn.pack(side="left")        frame2 = tk.Frame(self.window)        frame2.pack()        self.quoteText = tk.StringVar()  # 名言文本        tk.Label(frame2, textvariable=self.quoteText).pack()    def error(self,msg):        self.quoteText.set('Error:{}'.format(msg))    def show(self, quote):        self.quoteText.set('And the quote is:"{}"'.format(quote))class QuoteGUIController:    def __init__(self):        self.view = QuoteGUIView()        self.model = QuoteModel()    def run(self):        self.view.btn.bind("<Button-1>", self.btnClicked)        self.view.window.mainloop()    def btnClicked(self,event):        n=self.view.quoteNum.get()        try:            n=int(n)        except ValueError as err:            self.view.error("Incorrect index:"+n)        else:            quote = self.model.get_quote(n)            self.view.show(quote)if __name__ == '__main__':    controller=QuoteGUIController()    controller.run()


 
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 白色踏板摩托车把漆刮了怎么办 苹果手机用流量缓冲很难怎么办 谷歌浏览器安卓手机版打不开怎么办 怀孕四个月检查高型半氨酸高怎么办 猎豹cs9怎么打不开车门怎么办 孩子在学校被老师冤枉打板子怎么办 么司福利体检暗地查乙肝怎么办 上体育课时被老师罚了腿疼怎么办 义务兵学技术不好班长打他怎么办 耳朵被打了一巴掌听不见了怎么办 耳朵被打了一巴掌后有点闷怎么办 山东省教育云平台密码戳完怎么办 被舍友知道发朋友圈说她们了怎么办 苍蝇药水进眼里了眼睛疼怎么办 三十六周了胎儿还没有入骨盆怎么办 怀孕40周了宝宝还没反应怎么办 程序员不知道自己犯法了怎么办啊 大学档案学年测评有涂改痕迹怎么办 驼背怎么办要能快速矫正的方法 手臂往后扭后手臂根部疼又肿怎么办 一岁四个月宝宝有点斜颈怎么办? 六个月的宝宝脖子有点歪怎么办 情感交叉擦腿综合症心里治疗怎么办 坐月子受风了胳膊腿疼怎么办 劲椎手术两个月双腿疼痛麻这怎么办 手机里存的照片删除了怎么办 买了好几双鞋子都不防滑怎么办 电脑平车车加绒过厚不起线怎么办 碰见那种看不起人的店员应该怎么办 在食品厂上班載卫生帽头发痒怎么办 工司没给员工上保险离职后怎么办 货物被香港律政司扣了怎么办 室友考研要跟我考一样的学校怎么办 药流第一天才吃了一粒米非司怎么办 药流半月同房第二天大出血怎么办 口臭想让它变得不臭怎么办 来单位干了几天不满意想离职怎么办 药流吃药期间吃什么吐什么怎么办 养狗家里味道大怎么办养花有用吗 第一天上班站的脚疼怎么办 入职没有人事所需要的证书怎么办