python pyside2 List View(QListView) 作者:马育民 • 2025-09-17 22:21 • 阅读:10002 # 介绍 `QListView` 是 PySide2 中用于展示列表数据的控件,遵循 MVC(模型-视图-控制器)设计模式,通过模型与数据交互,视图负责展示。常与 `QStandardItemModel` 配合使用,支持多种显示模式和交互操作。 ### 应用场景 `QListView` 适合展示简单的列表数据 若需要更复杂的表格结构,可使用 `QTableView` 若需要树形结构,可使用 `QTreeView`。 # 例子 ``` import sys from PySide2.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout, QListView, QPushButton, QLineEdit, QLabel, QMessageBox) from PySide2.QtCore import Qt, QModelIndex from PySide2.QtGui import QStandardItemModel, QStandardItem, QFont class ListViewDemo(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): # 设置窗口基本属性 self.setWindowTitle("QListView 示例") self.setGeometry(300, 300, 500, 400) # 创建主布局 main_layout = QVBoxLayout() # 1. 创建列表视图和数据模型 self.list_view = QListView() # 创建标准项模型(用于存储列表数据) self.model = QStandardItemModel() self.list_view.setModel(self.model) # 设置列表视图属性 self.list_view.setEditTriggers(QListView.NoEditTriggers) # 禁止直接编辑 self.list_view.setSelectionMode(QListView.SingleSelection) # 单选模式 self.list_view.setAlternatingRowColors(True) # 交替行颜色 self.list_view.setFont(QFont("Segoe UI", 9)) # 设置字体 # 添加示例数据 self.init_list_data() # 2. 创建控制区域 control_layout = QVBoxLayout() # 添加项输入框和按钮 add_layout = QHBoxLayout() self.item_input = QLineEdit() self.item_input.setPlaceholderText("输入要添加的项...") add_btn = QPushButton("添加") add_btn.clicked.connect(self.add_item) add_layout.addWidget(self.item_input) add_layout.addWidget(add_btn) # 操作按钮 btn_layout = QHBoxLayout() self.remove_btn = QPushButton("删除选中项") self.remove_btn.clicked.connect(self.remove_selected) self.clear_btn = QPushButton("清空列表") self.clear_btn.clicked.connect(self.clear_list) btn_layout.addWidget(self.remove_btn) btn_layout.addWidget(self.clear_btn) # 状态显示 self.status_label = QLabel("选中项: 无") self.status_label.setStyleSheet("color: #666;") # 将控制组件添加到布局 control_layout.addLayout(add_layout) control_layout.addLayout(btn_layout) control_layout.addWidget(self.status_label) # 3. 组装主布局 main_layout.addWidget(QLabel("列表内容:")) main_layout.addWidget(self.list_view) main_layout.addLayout(control_layout) self.setLayout(main_layout) # 连接列表选择变化信号 self.list_view.selectionModel().selectionChanged.connect(self.on_selection_changed) self.show() def init_list_data(self): """初始化列表数据""" items = ["项目 1", "项目 2", "项目 3", "项目 4", "项目 5"] for item_text in items: item = QStandardItem(item_text) # 设置项的可选中、可启用 item.setSelectable(True) item.setEnabled(True) self.model.appendRow(item) def add_item(self): """添加新项到列表""" text = self.item_input.text().strip() if text: item = QStandardItem(text) self.model.appendRow(item) self.item_input.clear() # 清空输入框 else: QMessageBox.warning(self, "警告", "请输入内容后再添加!") def remove_selected(self): """删除选中的项""" selected_indexes = self.list_view.selectedIndexes() if selected_indexes: # 从模型中移除选中项 self.model.removeRow(selected_indexes[0].row()) else: QMessageBox.information(self, "提示", "请先选中要删除的项!") def clear_list(self): """清空列表""" if self.model.rowCount() > 0: reply = QMessageBox.question(self, "确认", "确定要清空所有项吗?", QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: self.model.clear() def on_selection_changed(self, selected, deselected): """处理选择变化事件""" indexes = selected.indexes() if indexes: # 获取选中项的文本 selected_text = self.model.data(indexes[0]) self.status_label.setText(f"选中项: {selected_text}") else: self.status_label.setText("选中项: 无") if __name__ == '__main__': app = QApplication(sys.argv) window = ListViewDemo() sys.exit(app.exec_()) ``` ### 核心用法解析 1. **基本组成** - `QListView`:负责列表的显示和交互 - `QStandardItemModel`:管理列表数据(模型) - `QStandardItem`:单个列表项的数据载体 2. **常用属性设置** - **编辑模式**:`setEditTriggers()` 控制是否允许直接编辑项(`NoEditTriggers` 为禁止编辑) - **选择模式**:`setSelectionMode()` 支持单选(`SingleSelection`)、多选(`MultiSelection`)等 - **外观设置**:`setAlternatingRowColors(True)` 启用交替行颜色,提升可读性 3. **数据操作** - 添加项:`model.appendRow(item)` - 删除项:`model.removeRow(row_index)` - 清空列表:`model.clear()` - 获取项数据:`model.data(index)` 4. **事件处理** - 通过 `selectionModel().selectionChanged` 信号捕获选择变化 - 可获取选中项的索引(`selectedIndexes()`)和数据 5. **进阶用法** - 可设置为图标模式:`list_view.setViewMode(QListView.IconMode)` - 支持拖放功能:`list_view.setDragEnabled(True)` 和 `list_view.setAcceptDrops(True)` - 可自定义项的外观(通过 `QItemDelegate`) # 高级用法- 隐藏数据项 在 `QListView` 中添加不需要显示但需要存储的数据(如ID、额外属性等),可以通过 **`QStandardItem` 的 `setData()` 方法** 来存储隐藏数据,这些数据不会在列表中显示,但可以在需要时通过 `data()` 方法获取。 ### 适用场景: - 存储列表项对应的ID(如数据库主键) - 保存额外的业务数据(如用户详情、文件路径等) - 记录项目状态(如是否已选中、优先级等) 这种方式既保持了列表的简洁显示,又能在需要时获取完整数据,是 `QListView` 处理复杂数据的常用技巧。 ### 核心实现原理: 1. **自定义数据角色** Qt 提供了 `Qt.UserRole` 及以上的角色值用于存储自定义数据,例如: ```python self.HIDDEN_DATA_ROLE = Qt.UserRole + 1 # 定义一个唯一的角色标识 ``` 不同角色可以存储不同类型的隐藏数据(如整数、字典、对象等)。 2. **存储隐藏数据** 使用 `QStandardItem` 的 `setData()` 方法将数据与自定义角色绑定: ```python item.setData(隐藏数据, 自定义角色) # 隐藏数据不会显示在列表中 ``` 支持存储多种类型数据(字符串、数字、字典、自定义对象等)。 3. **获取隐藏数据** 通过 `model.data(index, 自定义角色)` 方法提取隐藏数据: ```python hidden_data = self.model.data(index, self.HIDDEN_DATA_ROLE) ``` ### 例子 ``` import sys from PySide2.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout, QListView, QPushButton, QLabel, QMessageBox) from PySide2.QtCore import Qt, QModelIndex from PySide2.QtGui import QStandardItemModel, QStandardItem class ListViewHiddenData(QWidget): def __init__(self): super().__init__() # 定义一个角色用于存储隐藏数据(Qt提供的UserRole可自定义数据) self.HIDDEN_DATA_ROLE = Qt.UserRole + 1 # 自定义角色值 self.initUI() def initUI(self): self.setWindowTitle("QListView 隐藏数据示例") self.setGeometry(300, 300, 500, 400) # 创建列表视图和模型 self.list_view = QListView() self.model = QStandardItemModel() self.list_view.setModel(self.model) # 添加带隐藏数据的示例项 self.add_items_with_hidden_data() # 按钮:查看选中项的隐藏数据 self.show_data_btn = QPushButton("查看选中项的隐藏数据") self.show_data_btn.clicked.connect(self.show_hidden_data) # 布局 layout = QVBoxLayout() layout.addWidget(QLabel("列表项(显示名称):")) layout.addWidget(self.list_view) layout.addWidget(self.show_data_btn) self.setLayout(layout) self.show() def add_items_with_hidden_data(self): """添加带隐藏数据的项目""" # 示例数据:显示名称 + 隐藏数据(如ID、详情等) items = [ {"display": "用户A", "hidden": {"id": 101, "email": "a@example.com"}}, {"display": "用户B", "hidden": {"id": 102, "email": "b@example.com"}}, {"display": "用户C", "hidden": {"id": 103, "email": "c@example.com"}} ] for item_data in items: # 创建显示项(仅显示名称) item = QStandardItem(item_data["display"]) # 存储隐藏数据(使用自定义角色) item.setData(item_data["hidden"], self.HIDDEN_DATA_ROLE) # 添加到模型 self.model.appendRow(item) def show_hidden_data(self): """获取并显示选中项的隐藏数据""" selected_indexes = self.list_view.selectedIndexes() if not selected_indexes: QMessageBox.information(self, "提示", "请先选中一项") return # 获取选中项的索引 index = selected_indexes[0] # 获取显示文本 display_text = self.model.data(index) # 获取隐藏数据(通过自定义角色) hidden_data = self.model.data(index, self.HIDDEN_DATA_ROLE) # 显示结果 info = f"显示名称: {display_text}\n" info += f"隐藏ID: {hidden_data['id']}\n" info += f"隐藏邮箱: {hidden_data['email']}" QMessageBox.information(self, "隐藏数据详情", info) if __name__ == '__main__': app = QApplication(sys.argv) window = ListViewHiddenData() sys.exit(app.exec_()) ``` 原文出处:http://malaoshi.top/show_1GW1scJOxE0k.html