python pyside2 list widget(QListWidget) 作者:马育民 • 2025-09-18 18:58 • 阅读:10003 # 介绍 `QListWidget` 是 PySide2 中用于展示列表项的便捷控件,它是一种**自包含的列表组件**(内部集成了模型和视图),适合快速实现简单的列表功能。相比 `QListView`(需要手动关联模型),`QListWidget` 更简单易用,适合展示文本、图标等基础内容。 `QListWidget` 是简化版的列表控件,适合快速实现基础列表功能(如添加、删除、选择项),无需关注模型细节。如果需要更复杂的定制(如自定义项样式、复杂数据结构),则推荐使用 `QListView` 配合自定义模型。 ### 核心特点 - 自带数据模型,无需手动创建 `QStandardItemModel` - 支持添加 `QListWidgetItem` 类型的列表项 - 内置常用功能(如添加、删除、排序、多选选等) - 适合快速开发简单列表(如文件列表、选项列表等) ### 基本用法示例 以下是 `QListWidget` 的常用操作(添加项、删除项、获取选中项等): ``` import sys from PySide2.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout, QListWidget, QListWidgetItem, QPushButton, QLineEdit, QLabel, QMessageBox) from PySide2.QtCore import Qt from PySide2.QtGui import QIcon class ListWidgetDemo(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowTitle("QListWidget 示例") self.setGeometry(300, 300, 500, 400) # 1. 创建 QListWidget 控件 self.list_widget = QListWidget() # 设置列表属性 self.list_widget.setSelectionMode(QListWidget.ExtendedSelection) # 支持多选 self.list_widget.setAlternatingRowColors(True) # 交替行颜色 self.list_widget.setSortingEnabled(True) # 启用排序(点击表头可排序) # 2. 添加示例项 self.init_items() # 3. 控制按钮区域 # 添加项输入框 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() del_btn = QPushButton("删除选中项") del_btn.clicked.connect(self.delete_selected) clear_btn = QPushButton("清空列表") clear_btn.clicked.connect(self.list_widget.clear) show_btn = QPushButton("显示选中项") show_btn.clicked.connect(self.show_selected) btn_layout.addWidget(del_btn) btn_layout.addWidget(clear_btn) btn_layout.addWidget(show_btn) # 4. 组装布局 main_layout = QVBoxLayout() main_layout.addWidget(QLabel("列表内容:")) main_layout.addWidget(self.list_widget) main_layout.addLayout(add_layout) main_layout.addLayout(btn_layout) self.setLayout(main_layout) self.show() def init_items(self): """初始化列表项(支持文本、图标、隐藏数据)""" # 示例1:纯文本项 QListWidgetItem("项目 1", self.list_widget) QListWidgetItem("项目 2", self.list_widget) # 示例2:带图标项(实际使用时替换为真实图标路径) icon_item = QListWidgetItem("带图标项", self.list_widget) # icon_item.setIcon(QIcon("path/to/icon.png")) # 设置图标 # 示例3:带隐藏数据的项(使用 setData 存储) hidden_data_item = QListWidgetItem("带隐藏数据", self.list_widget) hidden_data_item.setData(Qt.UserRole + 1, {"id": 1001, "desc": "这是隐藏数据"}) def add_item(self): """添加新项到列表""" text = self.item_input.text().strip() if text: # 添加新项到列表末尾 QListWidgetItem(text, self.list_widget) self.item_input.clear() else: QMessageBox.warning(self, "警告", "请输入内容!") def delete_selected(self): """删除选中的项""" # 获取所有选中的项 selected_items = self.list_widget.selectedItems() if not selected_items: QMessageBox.information(self, "提示", "请先选中项!") return # 从列表中移除选中项 for item in selected_items: row = self.list_widget.row(item) # 获取项的行索引 self.list_widget.takeItem(row) # 移除项(不销毁对象) def show_selected(self): """显示选中项的信息(包括隐藏数据)""" selected_items = self.list_widget.selectedItems() if not selected_items: QMessageBox.information(self, "提示", "请先选中项!") return info = "" for i, item in enumerate(selected_items, 1): # 获取显示文本 text = item.text() # 获取隐藏数据(通过自定义角色) hidden_data = item.data(Qt.UserRole + 1) info += f"选中项 {i}:{text}\n" if hidden_data: info += f" 隐藏数据:{hidden_data}\n" QMessageBox.information(self, "选中项信息", info) if __name__ == '__main__': app = QApplication(sys.argv) window = ListWidgetDemo() sys.exit(app.exec_()) ``` ### 关键用法解析 #### 1. 基本操作 - **创建列表**:直接实例化 `QListWidget` 即可,无需单独创建模型。 - **添加项**:使用 `QListWidgetItem(text, list_widget)` 创建项并添加到列表,或通过 `list_widget.addItem(item)` 手动添加。 - **删除项**:通过 `takeItem(row)` 移除指定行的项(`row` 可通过 `row(item)` 获取)。 - **清空列表**:调用 `clear()` 方法快速清空所有项。 #### 2. 选择模式 通过 `setSelectionMode()` 设置选择行为: - `QListWidget.SingleSelection`:单选(默认) - `QListWidget.ExtendedSelection`:按住 `Ctrl` 或 `Shift` 多选 - `QListWidget.MultiSelection`:直接点击多选 - `QListWidget.NoSelection`:禁止选择 #### 3. 存储隐藏数据 与 `QListView` 类似,`QListWidgetItem` 支持通过 `setData()` 存储不显示的数据: ```python item = QListWidgetItem("显示文本", self.list_widget) # 用自定义角色存储隐藏数据(如ID、字典等) item.setData(Qt.UserRole + 1, {"id": 1001, "status": "active"}) # 获取隐藏数据 hidden_data = item.data(Qt.UserRole + 1) ``` # 设置选中 在 PySide2 中,`QListWidget` 提供了多种方法设置选中项,可根据需求选择直接选中单个项、多个项或按条件选中。以下是常用的实现方式及示例: ``` import sys from PySide2.QtWidgets import (QApplication, QWidget, QVBoxLayout, QListWidget, QListWidgetItem, QPushButton, QHBoxLayout, QLabel) from PySide2.QtCore import Qt class ListWidgetSelectionDemo(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowTitle("QListWidget 设置选中项示例") self.setGeometry(300, 300, 500, 400) # 创建布局 main_layout = QVBoxLayout() btn_layout = QHBoxLayout() # 创建QListWidget并添加项 self.list_widget = QListWidget() self.list_widget.setSelectionMode(QListWidget.ExtendedSelection) # 支持多选 self.items = ["项目1", "项目2", "项目3", "项目4", "项目5", "项目6"] for text in self.items: self.list_widget.addItem(text) # 创建操作按钮 self.btn_select_first = QPushButton("选中第一项") self.btn_select_last = QPushButton("选中最后一项") self.btn_select_by_text = QPushButton("选中'项目3'") self.btn_select_by_index = QPushButton("选中索引2的项") self.btn_select_all = QPushButton("全选") self.btn_deselect_all = QPushButton("取消全选") self.btn_select_even = QPushButton("选中偶数项") # 绑定按钮事件 self.btn_select_first.clicked.connect(self.select_first) self.btn_select_last.clicked.connect(self.select_last) self.btn_select_by_text.clicked.connect(self.select_by_text) self.btn_select_by_index.clicked.connect(self.select_by_index) self.btn_select_all.clicked.connect(self.list_widget.selectAll) self.btn_deselect_all.clicked.connect(self.list_widget.clearSelection) self.btn_select_even.clicked.connect(self.select_even_items) # 添加控件到布局 btn_layout.addWidget(self.btn_select_first) btn_layout.addWidget(self.btn_select_last) btn_layout.addWidget(self.btn_select_by_text) btn_layout.addWidget(self.btn_select_by_index) main_layout.addWidget(QLabel("列表项:")) main_layout.addWidget(self.list_widget) main_layout.addLayout(btn_layout) main_layout.addWidget(self.btn_select_all) main_layout.addWidget(self.btn_deselect_all) main_layout.addWidget(self.btn_select_even) self.setLayout(main_layout) self.show() # 方法1:选中第一项 def select_first(self): if self.list_widget.count() > 0: item = self.list_widget.item(0) # 获取第一项 item.setSelected(True) # 设置选中 self.list_widget.setCurrentItem(item) # 同步当前项 # 方法2:选中最后一项 def select_last(self): count = self.list_widget.count() if count > 0: item = self.list_widget.item(count - 1) # 获取最后一项 item.setSelected(True) # 方法3:按文本选中项 def select_by_text(self): target_text = "项目3" # 遍历所有项查找匹配文本 for i in range(self.list_widget.count()): item = self.list_widget.item(i) if item.text() == target_text: item.setSelected(True) break # 方法4:按索引选中项 def select_by_index(self): index = 2 # 第3项(索引从0开始) if 0 <= index < self.list_widget.count(): # 通过索引获取项并选中 self.list_widget.item(index).setSelected(True) # 或通过setCurrentRow直接选中行 # self.list_widget.setCurrentRow(index) # 方法5:按条件选中(示例:选中偶数索引项) def select_even_items(self): # 先取消现有选中 self.list_widget.clearSelection() # 选中偶数索引项(0, 2, 4...) for i in range(0, self.list_widget.count(), 2): self.list_widget.item(i).setSelected(True) if __name__ == '__main__': app = QApplication(sys.argv) window = ListWidgetSelectionDemo() sys.exit(app.exec_()) ``` ### 基本选中方法 ##### **`item.setSelected(True)`**:通过列表项对象设置选中状态(最常用) ```python item = self.list_widget.item(0) # 获取索引0的项 item.setSelected(True) # 选中 item.setSelected(False) # 取消选中 ``` ##### **`setCurrentRow(index)`**:通过行索引选中项(同时会设置为当前项) ```python self.list_widget.setCurrentRow(2) # 选中索引2的项 ``` ##### **`setCurrentItem(item)`**:通过项对象设置为当前选中项 ```python item = self.list_widget.item(1) self.list_widget.setCurrentItem(item) # 选中该项 ``` ### 批量选中方法 ##### **全选**:`selectAll()` ```python self.list_widget.selectAll() # 选中所有项(需开启多选模式) ``` ##### **取消全选**:`clearSelection()` ```python self.list_widget.clearSelection() # 取消所有选中项 ``` ##### **按条件选中**:遍历项并设置 `setSelected()` ```python # 示例:选中包含"关键词"的项 for i in range(self.list_widget.count()): item = self.list_widget.item(i) if "关键词" in item.text(): item.setSelected(True) ``` ### 选择模式设置 需先通过 `setSelectionMode()` 设置多选规则,否则部分批量选中方法无效: ```python # 常用选择模式 self.list_widget.setSelectionMode(QListWidget.SingleSelection) # 单选(默认) self.list_widget.setSelectionMode(QListWidget.MultiSelection) # 多选(点击即选) self.list_widget.setSelectionMode(QListWidget.ExtendedSelection) # 扩展多选(Ctrl/Shift辅助) ``` ### 注意事项 - 单选模式下,新选中项会自动取消之前的选中项; - `setCurrentRow()` 和 `setCurrentItem()` 不仅会选中项,还会将其设为“当前项”(带虚线边框); - 批量选中前最好用 `clearSelection()` 清空现有选中状态,避免冲突。 通过上述方法,可灵活实现 `QListWidget` 中各种选中需求,从简单的单项选到复杂的条件批量选都能覆盖。 # 获取选中的项 在 PySide2 中,`QListWidget` 获取选中值的方法取决于选择模式(单选/多选),常用方式有以下几种: ### 例子 ``` import sys from PySide2.QtWidgets import (QApplication, QWidget, QVBoxLayout, QListWidget, QListWidgetItem, QPushButton, QLabel, QHBoxLayout) from PySide2.QtCore import Qt class ListWidgetGetSelected(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowTitle("QListWidget 获取选中值") self.setGeometry(300, 300, 500, 400) # 主布局 main_layout = QVBoxLayout() # 创建列表并设置为多选模式 self.list_widget = QListWidget() self.list_widget.setSelectionMode(QListWidget.ExtendedSelection) # 支持Ctrl/Shift多选 # 添加示例项(同时存储隐藏数据) items = [ {"text": "项目A", "data": {"id": 101, "desc": "类型A"}}, {"text": "项目B", "data": {"id": 102, "desc": "类型B"}}, {"text": "项目C", "data": {"id": 103, "desc": "类型C"}}, {"text": "项目D", "data": {"id": 104, "desc": "类型D"}}, {"text": "项目E", "data": {"id": 105, "desc": "类型E"}} ] for item_data in items: item = QListWidgetItem(item_data["text"]) # 存储隐藏数据(使用UserRole) item.setData(Qt.UserRole, item_data["data"]) self.list_widget.addItem(item) # 按钮区域 btn_layout = QHBoxLayout() self.btn_get_single = QPushButton("获取当前选中项") self.btn_get_multi = QPushButton("获取所有选中项") self.btn_get_hidden = QPushButton("获取选中项隐藏数据") # 绑定按钮事件 self.btn_get_single.clicked.connect(self.get_single_selected) self.btn_get_multi.clicked.connect(self.get_multi_selected) self.btn_get_hidden.clicked.connect(self.get_hidden_data) # 结果显示标签 self.result_label = QLabel("选中项信息将显示在这里") self.result_label.setStyleSheet("border: 1px solid #eee; padding: 8px;") # 组装布局 btn_layout.addWidget(self.btn_get_single) btn_layout.addWidget(self.btn_get_multi) btn_layout.addWidget(self.btn_get_hidden) main_layout.addWidget(QLabel("请选择列表项:")) main_layout.addWidget(self.list_widget) main_layout.addLayout(btn_layout) main_layout.addWidget(QLabel("结果:")) main_layout.addWidget(self.result_label) self.setLayout(main_layout) self.show() # 方法1:获取当前选中的单个项(适合单选模式) def get_single_selected(self): # 获取当前选中项(当前项指带虚线边框的项) current_item = self.list_widget.currentItem() if current_item: self.result_label.setText(f"当前选中项:{current_item.text()}") else: self.result_label.setText("未选中任何项") # 方法2:获取所有选中项(适合多选模式) def get_multi_selected(self): # 获取所有选中的项 selected_items = self.list_widget.selectedItems() if not selected_items: self.result_label.setText("未选中任何项") return # 提取选中项的文本 selected_texts = [item.text() for item in selected_items] self.result_label.setText( f"共选中 {len(selected_texts)} 项:\n" + "\n".join(selected_texts) ) # 方法3:获取选中项的隐藏数据(如ID、额外属性) def get_hidden_data(self): selected_items = self.list_widget.selectedItems() if not selected_items: self.result_label.setText("未选中任何项") return # 提取隐藏数据(通过UserRole) hidden_info = [] for item in selected_items: data = item.data(Qt.UserRole) # 获取存储的隐藏数据 hidden_info.append( f"{item.text()} - ID: {data['id']}, 描述: {data['desc']}" ) self.result_label.setText( f"选中项隐藏数据:\n" + "\n".join(hidden_info) ) if __name__ == '__main__': app = QApplication(sys.argv) window = ListWidgetGetSelected() sys.exit(app.exec_()) ``` ### 获取单个选中项(适合单选模式) ##### **`currentItem()`**:返回当前获得焦点的项(带虚线边框的项) ```python current_item = self.list_widget.currentItem() if current_item: text = current_item.text() # 获取显示文本 ``` ##### **`currentRow()`**:返回当前选中项的索引,再通过索引获取项 ```python row = self.list_widget.currentRow() if row != -1: # -1表示无选中项 item = self.list_widget.item(row) text = item.text() ``` ### 获取所有选中项(适合多选模式) ##### **`selectedItems()`**:返回所有选中项的列表(`QListWidgetItem` 对象集合) ```python selected_items = self.list_widget.selectedItems() # 提取文本列表 selected_texts = [item.text() for item in selected_items] ``` ### 获取选中项的隐藏数据 如果项中存储了隐藏数据(通过 `setData()` 方法),可通过 `data()` 提取: ```python # 假设用 Qt.UserRole 存储了隐藏数据 for item in self.list_widget.selectedItems(): hidden_data = item.data(Qt.UserRole) # 获取隐藏数据 print(f"文本: {item.text()}, 隐藏数据: {hidden_data}") ``` ### 注意事项 - **选择模式影响结果**: - 单选模式(`SingleSelection`)下,`selectedItems()` 始终返回长度为 0 或 1 的列表 - 多选模式(`MultiSelection`/`ExtendedSelection`)下,返回所有选中项 - **空值判断**:操作前需判断是否有选中项(`currentItem()` 可能返回 `None`,`selectedItems()` 可能返回空列表) - **性能考虑**:对于大量选中项(上千项),遍历 `selectedItems()` 时需注意效率 通过上述方法,可根据实际需求灵活获取 `QListWidget` 中的选中值,包括显示文本和隐藏数据。 # 事件 在 PySide2 中,`QListWidget` 的事件用法主要围绕两类核心场景:**1. 利用其内置信号绑定槽函数(推荐,简单高效)**;**2. 重写事件处理方法(适用于深度定制交互逻辑)**。前者基于信号-槽机制,无需关注底层事件分发;后者需直接处理鼠标、键盘等原始事件,灵活性更高。 ### 一、核心:信号-槽机制(推荐优先使用) `QListWidget` 提供了大量封装好的**信号**,对应列表项的选中、点击、双击、删除等常见交互,直接绑定槽函数即可实现功能,无需手动解析事件。 #### 1. 常用信号及说明 | 信号名 | 触发时机 | 关键参数说明 | |---------------------------------|-------------------------------------------|---------------------------------------| | `itemClicked(QListWidgetItem *)`| 列表项被鼠标点击时 | 被点击的 `QListWidgetItem` 对象 | | `itemDoubleClicked(QListWidgetItem *)` | 列表项被双击时 | 被双击的 `QListWidgetItem` 对象 | | `currentItemChanged(QListWidgetItem *, QListWidgetItem *)` | 当前选中项变化时 | 新选中项、上一个选中项(均为对象) | | `itemSelectionChanged()` | 选中项集合变化时(如多选时勾选/取消勾选) | 无参数,需通过 `selectedItems()` 获取选中项 | | `itemPressed(QListWidgetItem *)`| 列表项被鼠标按下时(比 `itemClicked` 早) | 被按下的 `QListWidgetItem` 对象 | | `itemDeleted(QListWidgetItem *)`| 列表项被删除时 | 被删除的 `QListWidgetItem` 对象 | #### 2. 信号-槽完整示例 ```python from PySide2.QtWidgets import (QApplication, QMainWindow, QListWidget, QListWidgetItem, QLabel, QVBoxLayout, QWidget) import sys class ListWidgetSignalDemo(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowTitle("QListWidget 信号-槽示例") self.setGeometry(300, 300, 400, 300) # 中心Widget和布局 central_widget = QWidget() self.setCentralWidget(central_widget) layout = QVBoxLayout(central_widget) # 1. 创建QListWidget并添加项 self.list_widget = QListWidget() # 支持多选(可选,默认单选) self.list_widget.setSelectionMode(QListWidget.MultiSelection) # 添加测试项 items = ["项目1", "项目2", "项目3", "项目4", "项目5"] for item_text in items: # 可给项附加隐藏数据(通过setData存储,data读取) item = QListWidgetItem(item_text) item.setData(Qt.UserRole, f"隐藏数据_{item_text}") # 自定义角色存储额外信息 self.list_widget.addItem(item) # 2. 显示交互信息的标签 self.info_label = QLabel("请操作列表项(点击、双击、切换选中)") # 3. 绑定信号与槽函数 self.list_widget.itemClicked.connect(self.on_item_clicked) self.list_widget.itemDoubleClicked.connect(self.on_item_double_clicked) self.list_widget.currentItemChanged.connect(self.on_current_item_changed) self.list_widget.itemSelectionChanged.connect(self.on_selection_changed) # 添加控件到布局 layout.addWidget(self.list_widget) layout.addWidget(self.info_label) # ------------------------------ # 槽函数实现 # ------------------------------ def on_item_clicked(self, item: QListWidgetItem): """处理列表项点击事件""" text = item.text() hidden_data = item.data(Qt.UserRole) # 读取隐藏数据 self.info_label.setText(f"点击项: {text} | 隐藏数据: {hidden_data}") def on_item_double_clicked(self, item: QListWidgetItem): """处理列表项双击事件(示例:删除双击项)""" text = item.text() self.list_widget.takeItem(self.list_widget.row(item)) # 删除项 self.info_label.setText(f"双击删除项: {text}") def on_current_item_changed(self, new_item: QListWidgetItem, old_item: QListWidgetItem): """处理选中项变化事件""" if new_item: # 避免初始无选中项时的None self.info_label.setText(f"切换选中项: 从 {old_item.text() if old_item else '无'} 到 {new_item.text()}") def on_selection_changed(self): """处理多选时的选中集合变化""" selected_items = self.list_widget.selectedItems() # 获取所有选中项 selected_texts = [item.text() for item in selected_items] self.info_label.setText(f"当前选中项: {', '.join(selected_texts)}") if __name__ == "__main__": app = QApplication(sys.argv) window = ListWidgetSignalDemo() window.show() sys.exit(app.exec_()) ``` ### 二、进阶:重写事件处理方法(深度定制) 当信号-槽无法满足需求(如自定义鼠标右键菜单、拦截特定键盘按键、处理拖拽事件等)时,可通过**重写 `QListWidget` 的事件方法**或**安装事件过滤器**实现。 #### 1. 重写 `QListWidget` 自身的事件方法 直接继承 `QListWidget`,重写其 `mousePressEvent`、`keyPressEvent` 等方法,捕获原始事件。 ##### 示例:自定义右键菜单(重写鼠标按下事件) ```python from PySide2.QtWidgets import (QApplication, QMainWindow, QListWidget, QListWidgetItem, QMenu, QAction) from PySide2.QtCore import Qt import sys # 1. 继承QListWidget,重写事件方法 class CustomListWidget(QListWidget): def __init__(self, parent=None): super().__init__(parent) self.init_context_menu() # 初始化右键菜单 def init_context_menu(self): """创建右键菜单""" self.context_menu = QMenu(self) # 添加菜单动作 self.action_delete = QAction("删除选中项", self) self.action_delete.triggered.connect(self.delete_selected_items) self.action_clear = QAction("清空列表", self) self.action_clear.triggered.connect(self.clear) # 添加到菜单 self.context_menu.addAction(self.action_delete) self.context_menu.addAction(self.action_clear) def mousePressEvent(self, event): """重写鼠标按下事件:右键显示菜单""" # 先调用父类方法,确保正常的选中逻辑(如左键点击选中项) super().mousePressEvent(event) # 若右键点击,且点击位置有项 if event.button() == Qt.RightButton: # 获取右键点击位置对应的项 clicked_item = self.itemAt(event.pos()) if clicked_item: # 点击在项上 self.context_menu.exec_(event.globalPos()) # 显示菜单 def delete_selected_items(self): """删除选中项""" for item in self.selectedItems(): self.takeItem(self.row(item)) # 2. 主窗口使用自定义ListWidget class CustomEventDemo(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("QListWidget 重写事件示例") self.setGeometry(300, 300, 400, 300) # 使用自定义的ListWidget self.custom_list = CustomListWidget() # 添加测试项 for i in range(5): self.custom_list.addItem(f"自定义项{i+1}") self.setCentralWidget(self.custom_list) if __name__ == "__main__": app = QApplication(sys.argv) window = CustomEventDemo() window.show() sys.exit(app.exec_()) ``` #### 2. 安装事件过滤器(监控子控件或外部事件) 若不想修改 `QListWidget` 本身,可在其父控件上**安装事件过滤器**,监控 `QListWidget` 的所有事件(如拦截键盘按键)。 ##### 示例:拦截 "Delete" 键删除选中项 ```python from PySide2.QtWidgets import (QApplication, QMainWindow, QListWidget, QListWidgetItem) from PySide2.QtCore import QEvent, Qt import sys class EventFilterDemo(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowTitle("QListWidget 事件过滤器示例") self.setGeometry(300, 300, 400, 300) self.list_widget = QListWidget() for i in range(5): self.list_widget.addItem(f"过滤事件项{i+1}") self.setCentralWidget(self.list_widget) # 给list_widget安装事件过滤器(监控者是当前主窗口) self.list_widget.installEventFilter(self) def eventFilter(self, watched, event): """重写事件过滤器:watched是被监控的对象,event是事件""" # 仅处理list_widget的事件 if watched == self.list_widget: # 拦截键盘按键事件 if event.type() == QEvent.KeyPress: key = event.key() if key == Qt.Key_Delete: # 按下Delete键 # 删除选中项 for item in self.list_widget.selectedItems(): self.list_widget.takeItem(self.list_widget.row(item)) return True # 返回True表示事件已处理,不再传递 # 其他事件交给默认处理 return super().eventFilter(watched, event) if __name__ == "__main__": app = QApplication(sys.argv) window = EventFilterDemo() window.show() sys.exit(app.exec_()) ``` ### 三、关键注意事项 1. **信号-槽优先**:绝大多数常规需求(点击、选中、双击)都可通过信号-槽实现,无需重写事件,代码更简洁易维护。 2. **`QListWidgetItem` 的隐藏数据**:通过 `item.setData(Qt.UserRole, 数据)` 存储额外信息(如ID、路径),`item.data(Qt.UserRole)` 读取,避免仅依赖显示文本。 3. **事件传递顺序**:重写事件时,若需保留原有逻辑(如左键选中项),务必先调用 `super().xxxEvent(event)`。 4. **多选模式**:通过 `setSelectionMode()` 设置(如 `QListWidget.MultiSelection` 支持多选),多选时用 `selectedItems()` 获取所有选中项。 ### 总结 `QListWidget` 的事件用法分为「基础信号-槽」和「进阶事件重写/过滤」: - 简单交互(点击、选中、删除)→ 用 **信号-槽**; - 深度定制(右键菜单、拦截按键、拖拽)→ 用 **重写事件方法** 或 **事件过滤器**。 两者结合可覆盖几乎所有列表交互场景。 原文出处:http://www.malaoshi.top/show_1GW1sw0piA0c.html