PySide6 QTreeWidget自定义部件拖拽后消失问题求助
解决QTreeWidget拖拽自定义部件丢失的问题
拖拽后自定义部件丢失的核心原因是:QTreeWidget.setItemWidget()只是将部件临时关联到树项上,默认的内部拖拽操作仅处理树项的文本数据,不会同步保留关联的自定义部件引用,拖拽完成后部件与树项的关联会失效。
解决方案
通过以下两步修复:
- 将自定义部件的引用存入对应
QTreeWidgetItem的用户自定义数据字段,确保树项移动时部件引用不丢失 - 重写
dropEvent方法,在默认拖拽完成后重新为树项绑定自定义部件
修改后的完整代码
from PySide6 import QtWidgets, QtCore class CustomWidgetItem(QtWidgets.QWidget): def __init__(self, label_text, parent=None): super(CustomWidgetItem, self).__init__(parent) self.layout = QtWidgets.QHBoxLayout(self) self.label = QtWidgets.QLabel(label_text) self.button = QtWidgets.QPushButton("Custom Button") self.button.clicked.connect(self.btn_click) self.layout.addWidget(self.label) self.layout.addWidget(self.button) self.setLayout(self.layout) def btn_click(self): print(self.label.text()) class CustomTreeWidget(QtWidgets.QTreeWidget): def __init__(self, parent=None): super(CustomTreeWidget, self).__init__(parent) self.setHeaderHidden(True) self.setDragEnabled(True) self.setDragDropMode(QtWidgets.QTreeView.InternalMove) def dropEvent(self, event): source = event.source() if isinstance(source, QtWidgets.QTreeWidget): # 先执行默认的拖拽逻辑 super().dropEvent(event) # 拖拽完成后,遍历所有可见项,重新绑定自定义部件 iterator = QtWidgets.QTreeWidgetItemIterator(self) while iterator.value(): item = iterator.value() # 从用户数据中取出自定义部件引用 widget = item.data(0, QtCore.Qt.UserRole) if widget: self.setItemWidget(item, 0, widget) iterator += 1 else: event.setDropAction(QtCore.Qt.MoveAction) event.accept() class MainWindow(QtWidgets.QWidget): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setWindowTitle("Custom Tree Widget") self.layout = QtWidgets.QVBoxLayout(self) self.tree_widget = CustomTreeWidget() self.layout.addWidget(self.tree_widget) self.add_items() def add_items(self): for i in range(5): child_item = QtWidgets.QTreeWidgetItem(self.tree_widget, ['Group %d' % i]) custom_widget_item = QtWidgets.QTreeWidgetItem(child_item) custom_widget = CustomWidgetItem('Item %d' % i) # 把自定义部件存入树项的用户自定义数据 custom_widget_item.setData(0, QtCore.Qt.UserRole, custom_widget) # 设置部件 self.tree_widget.setItemWidget(custom_widget_item, 0, custom_widget) if __name__ == '__main__': app = QtWidgets.QApplication([]) window = MainWindow() window.show() app.exec()
关键修改点
- 在
add_items方法中,使用custom_widget_item.setData(0, QtCore.Qt.UserRole, custom_widget)将部件引用存入树项 - 在
CustomTreeWidget的dropEvent中,执行默认拖拽逻辑后,遍历树项,从用户数据中取出部件并重新调用setItemWidget绑定
内容的提问来源于stack exchange,提问作者Chris Hawkes
相关产品推荐
相关产品推荐

