QListWidget.data()切换含Action数据的Task Item时程序崩溃求助
问题:切换含Action数据的Task Item时程序崩溃
每个Task Item通过QListWidgetItem[]存储Action列表,点击Task Item时,Action视图区域从taskitem.data()重新加载数据。当所有Task Item均无Action数据时切换正常;仅存在一个含Action数据的Task Item时也无崩溃,但切换回该含Action数据的Task Item时程序崩溃。
复现步骤
- 添加一个Task Item并为其添加三个Action Item,多次点击该Task Item,程序无崩溃;
- 添加第二个Task Item且不为其添加任何Action Item;
- 切换回第一个含Action数据的Task Item时,程序崩溃。
原代码
# This Python file uses the following encoding: utf-8 import sys from typing import List from PySide6.QtCore import Qt from PySide6.QtWidgets import QApplication, QMainWindow, QListWidgetItem # Important: # You need to run the following command to generate the ui_form.py file # pyside6-uic form.ui -o ui_form.py, or # pyside2-uic form.ui -o ui_form.py from ui_form import Ui_MainWindow class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) item1 = QListWidgetItem("task 1") item2 = QListWidgetItem("task 2") self.ui.listWidget.addItem(item1) self.ui.listWidget.addItem(item2) action_data_list: List[QListWidgetItem] = [] action_data_list_2: List[QListWidgetItem] = [] action_data_list.append(QListWidgetItem("action 1")) action_data_list.append(QListWidgetItem("action 2")) self.ui.listWidget_2.addItem(action_data_list[0]) self.ui.listWidget_2.addItem(action_data_list[1]) item1.setData(Qt.UserRole, action_data_list) item2.setData(Qt.UserRole, action_data_list_2) self.ui.listWidget.itemClicked.connect(self.reload) # reload item to listWidget_2 def reload(self): current_item = self.ui.listWidget.currentItem() action_data_list = current_item.data(Qt.UserRole) for i in range(self.ui.listWidget_2.count()): self.ui.listWidget_2.takeItem(0) self.ui.listWidget_2.clear() for action_data in action_data_list: self.ui.listWidget_2.addItem(action_data) if __name__ == "__main__": app = QApplication(sys.argv) widget = MainWindow() widget.show() sys.exit(app.exec())
问题原因
QListWidgetItem不能被重复添加到QListWidget(包括同一列表多次)。第一次加载action_data_list到listWidget_2后,这些Item的父控件已经是listWidget_2。切换到无数据的Task Item时,通过takeItem和clear将这些Item从listWidget_2中移除,但Item的父控件关联并未完全清理。当再次尝试将这些Item添加回listWidget_2时,Qt的内部机制不允许重复添加同一Item,直接触发崩溃。
修复方案
方案1:存储Action文本数据而非QListWidgetItem对象
核心思路是分离数据与UI控件,存储Action的文本内容,每次加载时创建新的QListWidgetItem,避免复用同一Item对象。
修改后的完整代码:
# This Python file uses the following encoding: utf-8 import sys from typing import List from PySide6.QtCore import Qt from PySide6.QtWidgets import QApplication, QMainWindow, QListWidgetItem # Important: # You need to run the following command to generate the ui_form.py file # pyside6-uic form.ui -o ui_form.py, or # pyside2-uic form.ui -o ui_form.py from ui_form import Ui_MainWindow class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) item1 = QListWidgetItem("task 1") item2 = QListWidgetItem("task 2") self.ui.listWidget.addItem(item1) self.ui.listWidget.addItem(item2) # 存储文本数据而非QListWidgetItem对象 action_data_list: List[str] = ["action 1", "action 2"] action_data_list_2: List[str] = [] # 初始化加载第一个Task的Action for text in action_data_list: self.ui.listWidget_2.addItem(QListWidgetItem(text)) item1.setData(Qt.UserRole, action_data_list) item2.setData(Qt.UserRole, action_data_list_2) self.ui.listWidget.itemClicked.connect(self.reload) # reload item to listWidget_2 def reload(self): current_item = self.ui.listWidget.currentItem() action_data_list = current_item.data(Qt.UserRole) # 清空现有Action列表 self.ui.listWidget_2.clear() # 根据文本数据创建新的QListWidgetItem并添加 for action_text in action_data_list: self.ui.listWidget_2.addItem(QListWidgetItem(action_text)) if __name__ == "__main__": app = QApplication(sys.argv) widget = MainWindow() widget.show() sys.exit(app.exec())
方案2:复用Item时手动管理父控件(不推荐)
如果必须复用QListWidgetItem对象,需要在移除时将Item的父控件设置为None,但这种方式容易引入其他问题,不如方案1简洁可靠,示例代码如下:
在reload函数的移除步骤后添加:
for i in range(self.ui.listWidget_2.count()): item = self.ui.listWidget_2.takeItem(0) item.setParent(None) # 手动解除父控件关联
但依旧不建议使用此方案,因为Qt的UI控件生命周期管理复杂,存储数据而非UI对象是更合理的实践。
内容的提问来源于stack exchange,提问作者Skyrimaniac 17
相关产品推荐
相关产品推荐

