基于MVC原则构造一个TODO List交互工具
我们的总体目标是期望实现一个简单的待办事项列表应用程序。
应用程序允许用户添加、删除和标记待办事项为已完成。
代码应该遵循MVC(模型-视图-控制器)设计原则,将数据模型、视图和控制器分离,以便于维护和扩展。
功能概述
- 用户可以通过输入框输入待办事项。
- 点击“添加”按钮将待办事项添加到列表中。
- 用户可以选择列表中的待办事项,然后点击“删除”按钮删除选定的待办事项。
- 用户可以选择列表中的待办事项,然后点击“完成”按钮将选定的待办事项标记为已完成。
- 完成的待办事项会显示一个图标并变为不可编辑状态。
代码设计思路和原则
- 使用MVC设计原则,将数据模型、视图和控制器分离。这使得代码更容易维护和扩展。
- 创建一个自定义的TodoModel类,继承自QStandardItemModel。TodoModel中定义了添加、删除和完成待办事项的方法,这些方法封装了对数据模型的操作。这使得数据模型的逻辑与控制器和视图分离,便于维护。
- 创建一个自定义的TodoView类,继承自QListView。TodoView接受一个TodoModel实例作为参数,并将其设置为视图的模型。这使得视图可以显示和操作数据模型中的数据。
- MyMainWindow类作为控制器,负责处理用户界面事件(如按钮点击事件)。当用户执行操作(如添加、删除或完成待办事项)时,MyMainWindow会调用TodoModel的相应方法来更新数据。这使得控制器的逻辑与数据模型和视图分离,便于维护。
示例代码
代码语言:python代码运行次数:0复制from __future__ import annotations
import sys
from datetime import datetime
from PySide6.QtGui import QIcon, QStandardItem, QStandardItemModel
from PySide6.QtWidgets import QAbstractItemView, QApplication, QHBoxLayout, QLineEdit, QListView, QMainWindow, QPushButton,
QVBoxLayout, QWidget
def get_time_str() -> str:
return datetime.now().isoformat()
class TodoModel(QStandardItemModel):
def add_item(self, text: str):
item = QStandardItem('{} at {}'.format(text, get_time_str()))
item.setEditable(False)
self.appendRow(item)
def remove_item(self, index):
if index.isValid():
self.removeRow(index.row())
def complete_item(self, index):
if index.isValid():
item = self.itemFromIndex(index)
item.setIcon(QIcon('os_ubuntu_icon.png'))
item.setEnabled(False)
class TodoView(QListView):
def __init__(self, model: TodoModel):
super().__init__()
self.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
self.setObjectName('TODO列表视图效果展示')
self.setModel(model)
class MyMainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('ToDo List View Demo')
self.model = TodoModel()
self.view = TodoView(self.model)
self._setup_ui()
def _setup_ui(self):
# 横向布局
self.h_layout = QHBoxLayout()
self.delete_button = QPushButton('删除')
self.delete_button.clicked.connect(self.delete_button_clicked)
self.complete_button = QPushButton('完成')
self.complete_button.clicked.connect(self.complete_button_clicked)
self.h_layout.addWidget(self.delete_button)
self.h_layout.addWidget(self.complete_button)
self.line_edit = QLineEdit()
self.line_edit.setPlaceholderText('输入待办事项')
self.add_button = QPushButton('添加')
self.add_button.clicked.connect(self.add_button_clicked)
# 纵向布局
self.v_layout = QVBoxLayout()
self.v_layout.addWidget(self.view)
self.v_layout.addLayout(self.h_layout)
self.v_layout.addWidget(self.line_edit)
self.v_layout.addWidget(self.add_button)
self.container = QWidget()
self.container.setLayout(self.v_layout)
self.setCentralWidget(self.container)
def add_button_clicked(self, _: bool):
self.model.add_item(self.line_edit.text().strip())
self.line_edit.clear()
def delete_button_clicked(self):
self.model.remove_item(self.view.currentIndex())
def complete_button_clicked(self):
self.model.complete_item(self.view.currentIndex())
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyMainWindow()
window.show()
sys.exit(app.exec())