You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PySide6 QTreeWidget自定义部件拖拽后消失问题求助

解决QTreeWidget拖拽自定义部件丢失的问题

拖拽后自定义部件丢失的核心原因是:QTreeWidget.setItemWidget()只是将部件临时关联到树项上,默认的内部拖拽操作仅处理树项的文本数据,不会同步保留关联的自定义部件引用,拖拽完成后部件与树项的关联会失效。

解决方案

通过以下两步修复:

  1. 将自定义部件的引用存入对应QTreeWidgetItem的用户自定义数据字段,确保树项移动时部件引用不丢失
  2. 重写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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 03:05:32