MVC模式
在本文中,将介绍如何使用模型-视图-控制器 (MVC) 模式构建 Tkinter 应用程序。
1、MVC模式介绍
随着应用程序的增长,它的复杂性也会增加。 为了使应用程序更易于管理,可以使用模型-视图-控制器设计模式。
MVC 设计模式允许将应用程序分为三个主要组件:模型、视图和控制器。 这种结构可以帮助专注于每个部分的逻辑并使其更易于管理,尤其是在应用程序增长时。
下图说明了 MVC 设计模式:
1.1 Model
MVC 中的模型代表数据。 模型处理从数据库或文件等存储中获取数据或将数据写入其中。 该模型还可以包含验证数据以确保数据完整性的逻辑。
模型不能依赖于视图和控制器。 换句话说,可以在其他非 Tkinter 应用程序(例如 Web 和移动应用程序)中重用该模型。
1.2 View
视图是表示模型中数据的用户界面。 视图不直接与模型通信。 理想情况下,视图应该很少有逻辑来显示数据。
视图直接与控制器通信。 在 Tinker 应用程序中,视图是由小部件组成的根窗口。
1.3 Controller
控制器充当视图和模型之间的中介。 控制器在视图和模型之间路由数据。
例如,如果用户单击视图上的保存按钮,控制器会将“保存”操作路由到模型以将数据保存到数据库中并通知视图显示消息。
2、完整示例
下面将通过一个简单的示例来说明如何在 Tkinter 应用程序中应用 MVC 设计模式:
将构建的应用程序包含一个用于输入电子邮件的条目。 当单击保存按钮时,控制器会调用模型来验证电子邮件。
如果电子邮件有效,模型会将电子邮件保存到文本文件中,并且视图会显示成功消息:
如果电子邮件无效,视图会显示错误消息:
3 秒后隐藏消息。
2.1 Model类
下面定义了具有 email 属性的 Model 类:
class Model:
def __init__(self, email):
self.email = email
@property
def email(self):
return self.__email
@email.setter
def email(self, value):
"""
Validate the email
:param value:
:return:
"""
pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
if re.fullmatch(pattern, value):
self.__email = value
else:
raise ValueError(f'Invalid email address: {value}')
def save(self):
"""
Save the email into a file
:return:
"""
with open('emails.txt', 'a') as f:
f.write(self.email + '\n')
示例代码如何工作?
- 1)电子邮件设置器在将电子邮件分配给 __email 属性之前对其进行验证。 如果电子邮件无效,它将引发 ValueError。
- 2)save() 方法将电子邮件写入一个简单的文本文件。 在实际应用程序中,可能希望将其保存到数据库中。
2.2 View类
以下定义了显示表单以输入电子邮件的视图:
class View(ttk.Frame):
def __init__(self, parent):
super().__init__(parent)
self.label = ttk.Label(self, text='Email:')
self.label.grid(row=1, column=0)
self.email_var = tk.StringVar()
self.email_entry = ttk.Entry(self, textvariable=self.email_var, width=30)
self.email_entry.grid(row=1, column=1, sticky=tk.NSEW)
self.save_button = ttk.Button(self, text='Save', command=self.save_button_clicked)
self.save_button.grid(row=1, column=3, padx=10)
self.message_label = ttk.Label(self, text='', foreground='red')
self.message_label.grid(row=2, column=1, sticky=tk.W)
self.controller = None
def set_controller(self, controller):
"""
Set the controller
:param controller:
:return:
"""
self.controller = controller
def save_button_clicked(self):
"""
Handle button click event
:return:
"""
if self.controller:
self.controller.save(self.email_var.get())
def show_error(self, message):
"""
Show an error message
:param message:
:return:
"""
self.message_label['text'] = message
self.message_label['foreground'] = 'red'
self.message_label.after(3000, self.hide_message)
self.email_entry['foreground'] = 'red'
def show_success(self, message):
"""
Show a success message
:param message:
:return:
"""
self.message_label['text'] = message
self.message_label['foreground'] = 'green'
self.message_label.after(3000, self.hide_message)
self.email_entry['foreground'] = 'black'
self.email_var.set('')
def hide_message(self):
"""
Hide the message
:return:
"""
self.message_label['text'] = ''
代码如何工作?
- 第一步,在
__init__() 方法中创建小部件。 - 第二步,定义 set_controller() 方法来设置控制器。
- 第三步,在保存按钮的点击事件处理函数中调用控制器的save()方法。
- 第四步,定义 show_error()、show_success() 和 hide_message() 方法来显示/隐藏消息。
2.3 Controller类
下面定义了一个控制器:
class Controller:
def __init__(self, model, view):
self.model = model
self.view = view
def save(self, email):
"""
Save the email
:param email:
:return:
"""
try:
self.model.email = email
self.model.save()
self.view.show_success(f'The email {email} saved!')
except ValueError as error:
self.view.show_error(error)
上面代码如何工作?
- 首先,在
__init__() 方法中分配模型和视图 - 其次,定义将模型保存到文本文件中的 save() 方法。 如果模型保存成功,则显示成功消息。 否则,显示错误消息。
2.4 启动应用程序
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title('Tkinter MVC Demo')
model = Model('hello@pythontutorial.net')
view = View(self)
view.grid(row=0, column=0, padx=10, pady=10)
controller = Controller(model, view)
view.set_controller(controller)
if __name__ == '__main__':
app = App()
app.mainloop()
|