PyQt5 中的 List View

1. 基础概念

  • 用途
    • List View 是 PyQt5 中用于显示列表数据的重要组件之一。它可以在界面上以列表的形式展示多行数据,通常用于显示诸如文件列表、联系人列表、日程安排等等的数据。
  • 特性
    • List View 具有灵活的布局和显示方式,可以根据需要进行自定义。它支持多种交互方式,比如点击、双击、拖拽等。同时,List View 也支持排序、过滤、编辑等功能,使用户能够更方便地管理和操作列表中的数据。
  • 基本工作原理
    • List View 基于模型-视图架构工作。它通过与数据模型进行交互来显示数据,并且可以使用不同的模型来管理不同类型的数据。List View 通过视图部件以及布局来展示数据,并通过委托来控制每个数据项的显示方式。
  • 视图和模型
    • 在 PyQt5中,List View 是视图(View)部件,用于显示数据;而数据模型(Model)则负责管理数据的存储和操作。通常情况下,可以使用 PyQt5 提供的标准模型(如 QStandardItemModel)来管理数据,也可以自定义模型来满足特定需求。
  • 定制化
    • List View 可以通过设置不同的属性和样式来进行定制化,比如调整行高、列宽、文本颜色、背景色等。此外,还可以通过设置委托(Delegate)来实现更高级的定制化,比如自定义每个数据项的显示方式或交互方式。

2. 创建 List View

2.1 PyQt5 中一个简单的 List View 实例

​ 下面我们用PyQt5 创建一个简单的 List View 实例,并展示一些静态数据

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QListView
from PyQt5.QtCore import QStringListModel

class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        # 设置窗口标题和大小
        self.setWindowTitle("Simple List View Example")
        self.resize(500, 300)

        # 创建数据模型并填充数据
        data = ["Apple", "Banana", "Orange", "Grapes", "Pineapple"]
        self.model = QStringListModel()
        self.model.setStringList(data)

        # 创建 List View 实例并设置数据模型
        self.list_view = QListView()
        self.list_view.setModel(self.model)

        # 创建主窗口布局
        layout = QVBoxLayout()
        layout.addWidget(self.list_view)

        # 创建主窗口部件并设置布局
        central_widget = QWidget()
        central_widget.setLayout(layout)
        self.setCentralWidget(central_widget)

if __name__ == "__main__":
    # 创建应用程序对象
    app = QApplication(sys.argv)
    
    # 创建主窗口对象
    window = MyMainWindow()
    
    # 显示主窗口
    window.show()
    
    # 进入应用程序的主事件循环
    sys.exit(app.exec_())

2.2 代码解释

  • from PyQt5.QtCore import QStringListModel: 导入 PyQt5 中的 QStringListModel 类,用于管理 List View 的数据模型。
  • self.setWindowTitle("Simple List View Example"): 设置主窗口的标题。
  • self.resize(500, 300): 设置主窗口的大小为宽度 500 像素、高度 300 像素。
  • data = ["Apple", "Banana", "Orange", "Grapes", "Pineapple"]: 定义一个包含静态数据的列表。
  • self.model = QStringListModel(): 创建一个 QStringListModel 对象,用于管理 List View 的数据模型。
  • self.model.setStringList(data): 将静态数据添加到数据模型中。
  • self.list_view = QListView(): 创建一个 QListView 对象,用于显示数据列表。
  • self.list_view.setModel(self.model): 将数据模型设置为 List View 的模型。
  • layout = QVBoxLayout(): 创建一个垂直布局管理器。
  • layout.addWidget(self.list_view): 将 List View 添加到布局中。
  • central_widget = QWidget(): 创建一个 QWidget 对象作为主窗口的中央部件。
  • central_widget.setLayout(layout): 将布局设置为中央部件的布局。
  • self.setCentralWidget(central_widget): 将中央部件设置为主窗口的中央部件。

2.3 运行结果

在这里插入图片描述

3. 数据模型

在 PyQt5 中,数据模型是一种用于管理 List View 中数据的重要概念。数据模型负责存储、组织和操作列表视图中显示的数据。PyQt5 提供了两种主要类型的数据模型:标准模型和自定义模型。

3.1 标准模型

  • PyQt5 提供了一些标准的数据模型类,最常用的是 QStandardItemModel 和 QStringListModel。

  • QStandardItemModel:适用于一般的数据展示,可以存储各种类型的数据,每个数据项都可以包含文本、图标等内容。

  • QStringListModel:专门用于管理字符串列表的数据模型,可以方便地将字符串列表显示在 List View 中。

    from PyQt5.QtCore import QStringListModel
    
    # 创建 QStringListModel 数据模型
    model = QStringListModel()
    
    # 填充数据到模型中
    data = ["Apple", "Banana", "Orange", "Grapes", "Pineapple"]
    model.setStringList(data)
    
    

3.2 自定义模型

  • 有时候,标准模型可能无法满足特定的需求,这时可以自定义数据模型。

  • 自定义模型需要继承自 QAbstractItemModel 类,并实现一些关键的方法,如 data()、rowCount()、columnCount() 等,以便 List View 能够正确地显示数据。

    from PyQt5.QtCore import QAbstractItemModel, QModelIndex, Qt
    
    # 自定义数据模型类
    class CustomModel(QAbstractItemModel):
        def __init__(self, data, parent=None):
            super().__init__(parent)
            self.data = data
    
        def rowCount(self, parent=QModelIndex()):
            return len(self.data)
    
        def columnCount(self, parent=QModelIndex()):
            return 1
    
        def data(self, index, role=Qt.DisplayRole):
            if role == Qt.DisplayRole:
                return self.data[index.row()]
            return None
    
    # 使用自定义模型
    data = ["Apple", "Banana", "Orange", "Grapes", "Pineapple"]
    model = CustomModel(data)
    

4. 自定义 List View

在 PyQt5 中,自定义 List View 的外观和行为可以通过多种方式实现,包括使用样式表 (QSS)、设置项委托 (Item Delegate) 以及直接修改 List View 的属性。

4.1 使用样式表 (QSS)

样式表类似于 CSS,可以用于修改控件的外观。

from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QListView
from PyQt5.QtCore import QStringListModel
import sys

class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Custom List View Example")
        self.resize(500, 300)

        # 创建数据模型并填充数据
        data = ["Apple", "Banana", "Orange", "Grapes", "Pineapple"]
        self.model = QStringListModel()
        self.model.setStringList(data)

        # 创建 List View 实例并设置数据模型
        self.list_view = QListView()
        self.list_view.setModel(self.model)

        # 使用样式表自定义 List View 的外观
        self.list_view.setStyleSheet("""
            QListView {
                background-color: #f0f0f0;
                alternate-background-color: #e0e0e0;
                padding: 10px;
            }
            QListView::item {
                height: 40px;
            }
            QListView::item:selected {
                background-color: #a0a0ff;
                color: white;
            }
        """)

        # 创建主窗口布局
        layout = QVBoxLayout()
        layout.addWidget(self.list_view)

        # 创建主窗口部件并设置布局
        central_widget = QWidget()
        central_widget.setLayout(layout)
        self.setCentralWidget(central_widget)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyMainWindow()
    window.show()
    sys.exit(app.exec_())

结果如下:

在这里插入图片描述

4.2 设置项委托 (Item Delegate)

项委托可以自定义每个项的绘制和编辑行为。

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QListView, QStyledItemDelegate, QStyle
from PyQt5.QtCore import QStringListModel, QRect, QSize, Qt
from PyQt5.QtGui import QPainter, QColor, QFont


class CustomDelegate(QStyledItemDelegate):
    def paint(self, painter, option, index):
        painter.save()

        # 获取当前项的矩形区域
        rect = option.rect

        # 检查项的选择状态并设置相应的背景颜色
        if option.state & QStyle.State_Selected:
            painter.fillRect(rect, QColor("#D3D3D3"))  # 灰色背景
        else:
            painter.fillRect(rect, QColor("#FFFFFF"))  # 白色背景

        # 获取要显示的文本
        text = index.data()

        # 设置自定义字体和颜色
        font = QFont("Arial", 14)
        painter.setFont(font)
        painter.setPen(QColor("#000000"))  # 黑色字体

        # 绘制文本
        painter.drawText(rect, Qt.AlignLeft | Qt.AlignVCenter, text)

        painter.restore()

    def sizeHint(self, option, index):
        # 自定义每个项的高度
        return QSize(option.rect.width(), 40)


class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Custom List View Example")
        self.resize(500, 300)

        # 创建数据模型并填充数据
        data = ["Apple", "Banana", "Orange", "Grapes", "Pineapple"]
        self.model = QStringListModel()
        self.model.setStringList(data)

        # 创建 List View 实例并设置数据模型
        self.list_view = QListView()
        self.list_view.setModel(self.model)

        # 设置自定义委托
        self.list_view.setItemDelegate(CustomDelegate())

        # 创建主窗口布局
        layout = QVBoxLayout()
        layout.addWidget(self.list_view)

        # 创建主窗口部件并设置布局
        central_widget = QWidget()
        central_widget.setLayout(layout)
        self.setCentralWidget(central_widget)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyMainWindow()
    window.show()
    sys.exit(app.exec_())

运行结果如下:

在这里插入图片描述

5.事件处理

  • 下面例子处理 List View 中的点击事件。

    import sys
    from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QListView, QMessageBox
    from PyQt5.QtCore import QStringListModel
    
    class MyMainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
    
            self.setWindowTitle("List View Event Handling Example")
            self.resize(300, 200)
    
            # 创建数据模型并填充数据
            data = ["Apple", "Banana", "Orange", "Grapes", "Pineapple"]
            self.model = QStringListModel()
            self.model.setStringList(data)
    
            # 创建 List View 实例并设置数据模型
            self.list_view = QListView()
            self.list_view.setModel(self.model)
    
            # 连接 List View 的点击事件到相应的处理函数
            self.list_view.clicked.connect(self.on_item_clicked)
    
            # 创建主窗口布局
            layout = QVBoxLayout()
            layout.addWidget(self.list_view)
    
            # 创建主窗口部件并设置布局
            central_widget = QWidget()
            central_widget.setLayout(layout)
            self.setCentralWidget(central_widget)
    
        def on_item_clicked(self, index):
            # 获取点击项的文本
            item_text = index.data()
            # 显示消息框
            QMessageBox.information(self, "Item Clicked", f"You clicked: {item_text}")
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        window = MyMainWindow()
        window.show()
        sys.exit(app.exec_())
    
    

    运行结果如下:

    在这里插入图片描述

6. 与数据交互

​ 当与 PyQt5 中的 QListView 进行交互时,可以通过操作数据模型来实现添加、删除和编辑数据等操作。

6.1 添加数据

​ 要向 List View 中添加数据,可以直接修改数据模型。例如,对于 QStringListModel,可以使用 insertRows 方法或 append 方法添加新项。

# 创建数据模型
model = QStringListModel()

# 添加新项
new_item = "New Item"
model.insertRows(model.rowCount(), 1)
model.setData(model.index(model.rowCount() - 1), new_item)

6.2 删除数据

​ 删除数据与添加数据类似,也是通过操作数据模型来实现。对于 QStringListModel,可以使用 removeRows 方法删除指定位置的项。

# 删除选定项
selected_index = list_view.selectedIndexes()[0]
model.removeRows(selected_index.row(), 1)

6.3 编辑数据

​ 要编辑 List View 中的数据,需要捕获用户的编辑动作,并更新相应的数据模型。可以通过重载委托类的 setEditorDatasetModelData 方法来实现。

class CustomDelegate(QStyledItemDelegate):
    def setEditorData(self, editor, index):
        # 获取当前项的文本
        text = index.data()
        # 将文本设置到编辑器中
        editor.setText(text)

    def setModelData(self, editor, model, index):
        # 获取编辑器中的文本
        text = editor.text()
        # 更新数据模型
        model.setData(index, text)

6.4 完整示例

下面是一个完整的示例,演示如何使用 PyQt5 实现添加、删除和编辑 List View 中的数据

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QListView, QPushButton, QLineEdit, QMessageBox, QStyledItemDelegate
from PyQt5.QtCore import QStringListModel, Qt

class CustomDelegate(QStyledItemDelegate):
    def setEditorData(self, editor, index):
        # 获取当前项的文本
        text = index.data()
        # 将文本设置到编辑器中
        editor.setText(text)

    def setModelData(self, editor, model, index):
        # 获取编辑器中的文本
        text = editor.text()
        # 更新数据模型
        model.setData(index, text)

class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("List View Interaction Example")
        self.resize(300, 200)

        # 创建数据模型并填充数据
        self.model = QStringListModel()
        self.model.setStringList(["Apple", "Banana", "Orange"])

        # 创建 List View 实例并设置数据模型
        self.list_view = QListView()
        self.list_view.setModel(self.model)
        self.list_view.setItemDelegate(CustomDelegate())

        # 创建按钮和文本框
        self.add_button = QPushButton("Add")
        self.remove_button = QPushButton("Remove")
        self.edit_text = QLineEdit()
        self.add_button.clicked.connect(self.add_item)
        self.remove_button.clicked.connect(self.remove_item)

        # 创建主窗口布局
        layout = QVBoxLayout()
        layout.addWidget(self.list_view)
        layout.addWidget(self.add_button)
        layout.addWidget(self.remove_button)
        layout.addWidget(self.edit_text)

        # 创建主窗口部件并设置布局
        central_widget = QWidget()
        central_widget.setLayout(layout)
        self.setCentralWidget(central_widget)

    def add_item(self):
        # 获取要添加的文本
        new_item = self.edit_text.text().strip()
        if new_item:
            # 添加新项到数据模型
            self.model.insertRows(self.model.rowCount(), 1)
            self.model.setData(self.model.index(self.model.rowCount() - 1), new_item)
            # 清空文本框
            self.edit_text.clear()
        else:
            QMessageBox.warning(self, "Warning", "Please enter a valid item.")

    def remove_item(self):
        # 获取选定项的索引
        selected_indexes = self.list_view.selectedIndexes()
        if selected_indexes:
            # 删除选定项
            self.model.removeRows(selected_indexes[0].row(), 1)
        else:
            QMessageBox.warning(self, "Warning", "Please select an item to remove.")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyMainWindow()
    window.show()
    sys.exit(app.exec_())

运行结果如下:

在这里插入图片描述

7. 排序与过滤

在 PyQt5 中,可以通过使用 QSortFilterProxyModel 类来实现 List View 的排序和过滤功能。这个类可以作为数据模型的中介,允许对模型中的数据进行排序和过滤,而不改变原始模型的数据。下面是如何在 List View 中实现排序和过滤功能的简要步骤:

步骤概览

  1. 创建原始数据模型:通常使用 QStringListModel 或自定义的模型类。
  2. 创建 QSortFilterProxyModel 对象,并将原始数据模型设置为其源模型。
  3. QSortFilterProxyModel 设置为 List View 的模型。
  4. 设置 QSortFilterProxyModel 的排序和过滤规则。
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QListView, QLineEdit, QLabel, QSortFilterProxyModel
from PyQt5.QtCore import QStringListModel

class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("List View Sorting and Filtering Example")
        self.resize(300, 200)

        # 创建原始数据模型并填充数据
        self.original_model = QStringListModel()
        self.original_model.setStringList(["Apple", "Banana", "Orange", "Grapes", "Pineapple"])

        # 创建排序和过滤代理模型
        self.proxy_model = QSortFilterProxyModel()
        self.proxy_model.setSourceModel(self.original_model)

        # 创建 List View 实例并设置模型为代理模型
        self.list_view = QListView()
        self.list_view.setModel(self.proxy_model)

        # 创建文本框和标签用于输入和显示过滤文本
        self.filter_edit = QLineEdit()
        self.filter_edit.textChanged.connect(self.filter_items)
        self.filter_label = QLabel("Filter:")
        
        # 创建主窗口布局
        layout = QVBoxLayout()
        layout.addWidget(self.filter_label)
        layout.addWidget(self.filter_edit)
        layout.addWidget(self.list_view)

        # 创建主窗口部件并设置布局
        central_widget = QWidget()
        central_widget.setLayout(layout)
        self.setCentralWidget(central_widget)

    def filter_items(self):
        # 获取过滤文本
        filter_text = self.filter_edit.text()
        # 设置过滤正则表达式
        self.proxy_model.setFilterRegExp(filter_text)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyMainWindow()
    window.show()
    sys.exit(app.exec_())

运行结果如下:

在这里插入图片描述

8. 总结

在这篇文章中,我们涵盖了 PyQt5 中 QListView 的各种功能和用法,包括List View 的基本概念,展示了如何使用 PyQt5 创建一个简单的 List View 实例,介绍了如何使用数据模型来管理 List View 中的数据,包括标准模型(如 QStringListModel)和自定义模型,我们讨论了如何自定义 List View 的外观和行为,包括调整行高、列宽、背景色等。我们介绍了如何设置项委托,以自定义 List View 中项的编辑器和显示器。我们讨论了如何处理 List View 中的事件,例如点击,并为这些事件添加相应的处理函数。我们展示了如何在 List View 中实现添加、删除、编辑数据等操作,以及如何使用自定义委托类来编辑数据。最后,我们介绍了如何使用 QSortFilterProxyModel 类来实现 List View 的排序和过滤功能,使用户能够更轻松地查找和管理数据。

总的来说,通过这些内容,读者可以了解到如何有效地使用 PyQt5 中的 QListView 组件,并根据自己的需求进行定制和扩展。

  • 18
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xy_optics

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值