PySide6 GUI 编程(40):MVC 设计原则下QListView的使用

2024-09-01 21:28:36 浏览数 (3)

基于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())

静态效果

静态效果静态效果

动态效果

创建、删除与已完成创建、删除与已完成

0 人点赞