Pyside2:如何保持QtreeWidgetItem小部件?

发布于 2025-02-10 21:53:28 字数 3463 浏览 2 评论 0原文

我的自定义Qtreewidget丢失了每个QtreeWidgetItem的QTREEWIDGET,当它被拖动和掉落时。我知道这是由于该物品因其新位置而被摧毁和重新创建,并且我相信它与Qmimetype有关吗?但是我不确定如何解决此问题以使其工作并保留/重新创建这些小部件?我可能会不愿意的&对他们进行修复,不知何故?我能找到的示例主要是在QT中,我可以阅读,但是我不确定如何在Pyside2/pyqt中实现解决方案。有人可以给我任何指针吗?

我的代码是为Maya编写的,但希望它也应该能够在Maya之外工作。 (由于Maya/MAC的错误导致拖放操作以完全删除掉落的项目,因此需要自定义的Dropevent。)您可以看到该项目5已被重新订购,但丢失了它是关联的按钮。

import sys
from PySide2 import QtCore, QtWidgets


def main():
    try:
        app = QtWidgets.QApplication(sys.argv)
        ui = TreeUI()
        ui.show()
        app.exec_()
    except RuntimeError:
        from maya import OpenMayaUI as omui
        try:
            import shiboken2 as shiboken
        except ImportError:
            import shiboken
        pointer = omui.MQtUtil.mainWindow()
        win = shiboken.wrapInstance(long(pointer), QtWidgets.QWidget)
        ui = TreeUI(parent=win)
        ui.show()


class Tree(QtWidgets.QTreeWidget):

    def __init__(self, parent=None):
        super(Tree, self).__init__(parent)
        self.setHeaderLabels(('name', 'widget'))
        self.setSelectionMode(self.SingleSelection)
        self.setDragEnabled(True)
        self.setDropIndicatorShown(True)
        self.setDragDropMode(self.InternalMove)
        self.reparented_widgets = {}

    def dropEvent(self, event):
        index = self.indexAt(event.pos())
        parent = index.parent()
        self.model().dropMimeData(
            event.mimeData(),
            event.dropAction(),
            index.row(),
            index.column(),
            parent
        )
        event.accept()


class TreeUI(QtWidgets.QMainWindow):

    def __init__(self, parent=None):
        super(TreeUI, self).__init__(parent)
        widget = QtWidgets.QWidget(self)
        self.setCentralWidget(widget)
        tree = Tree()
        for x in range(0, 6):
            item = QtWidgets.QTreeWidgetItem(tree, ('item{}'.format(x), None))
            item.setFlags(item.flags() & ~QtCore.Qt.ItemIsDropEnabled)
            button = QtWidgets.QPushButton('Button{}'.format(x))
            tree.setItemWidget(item, 1, button)
        layout = QtWidgets.QVBoxLayout(widget)
        layout.addWidget(tree)


main()

更新#1: 我可以在startdrag函数中存储qtreewidgetItem的小部件,同时将其从项目中删除。但是,当我去将它们添加回新的QtreewidgetItem时,该应用程序崩溃了,不幸的是...

    def startDrag(self, actions):
        column_count = self.columnCount()
        items = self.selectedItems()
        for item in items:
            for x in range(column_count):
                widget = self.itemWidget(item, x)
                if widget:
                    self.removeItemWidget(item, x)
                    self.reparent_widgets[x] = widget
        super(Tree, self).startDrag(actions)

    def dropEvent(self, event):
        # Fix Mac/Maya drag and drop bug
        index = self.indexAt(event.pos())
        parent = index.parent()
        self.model().dropMimeData(
            event.mimeData(),
            event.dropAction(),
            index.row(),
            index.column(),
            parent
        )
        event.accept()
        # Re-create widget(s)
        pos = event.pos()
        item = self.itemAt(pos)
        for x in self.reparent_widgets.keys():
            self.setItemWidget(item, x, self.reparent_widgets[x])

I have a problem with my custom QTreeWidget losing the associated widgets for each QTreeWidgetItem when it gets dragged and dropped. I understand that this is due to the item being destroyed and re-created at it's new position, and that it has something to do with the QMimeType, I believe? But I'm not sure how to work around this to get it to work and preserve/re-create these widgets? Could I possibly un-parent & reparent them, somehow? The examples I've been able to find have largely been in QT, which I can read, but I'm not really sure how to implement a solution in PySide2/PyQt. Would anybody be able to give me any pointers?

My code is written for Maya, but hopefully it should be able to work outside of Maya as well. (The custom dropEvent is needed due to a Maya/Mac bug that causes drag and drop actions to completely remove the item on drop.) You can see that item5 has been re-ordered, but lost it's associated button.

QTreeWidget loses QPushButton

import sys
from PySide2 import QtCore, QtWidgets


def main():
    try:
        app = QtWidgets.QApplication(sys.argv)
        ui = TreeUI()
        ui.show()
        app.exec_()
    except RuntimeError:
        from maya import OpenMayaUI as omui
        try:
            import shiboken2 as shiboken
        except ImportError:
            import shiboken
        pointer = omui.MQtUtil.mainWindow()
        win = shiboken.wrapInstance(long(pointer), QtWidgets.QWidget)
        ui = TreeUI(parent=win)
        ui.show()


class Tree(QtWidgets.QTreeWidget):

    def __init__(self, parent=None):
        super(Tree, self).__init__(parent)
        self.setHeaderLabels(('name', 'widget'))
        self.setSelectionMode(self.SingleSelection)
        self.setDragEnabled(True)
        self.setDropIndicatorShown(True)
        self.setDragDropMode(self.InternalMove)
        self.reparented_widgets = {}

    def dropEvent(self, event):
        index = self.indexAt(event.pos())
        parent = index.parent()
        self.model().dropMimeData(
            event.mimeData(),
            event.dropAction(),
            index.row(),
            index.column(),
            parent
        )
        event.accept()


class TreeUI(QtWidgets.QMainWindow):

    def __init__(self, parent=None):
        super(TreeUI, self).__init__(parent)
        widget = QtWidgets.QWidget(self)
        self.setCentralWidget(widget)
        tree = Tree()
        for x in range(0, 6):
            item = QtWidgets.QTreeWidgetItem(tree, ('item{}'.format(x), None))
            item.setFlags(item.flags() & ~QtCore.Qt.ItemIsDropEnabled)
            button = QtWidgets.QPushButton('Button{}'.format(x))
            tree.setItemWidget(item, 1, button)
        layout = QtWidgets.QVBoxLayout(widget)
        layout.addWidget(tree)


main()

UPDATE #1:
I'm able to store the widgets for the QTreeWidgetItem within the startDrag function, while removing them from the item. But then, when I go to add them back to the new QTreeWidgetItem, the application crashes, unfortunately...

    def startDrag(self, actions):
        column_count = self.columnCount()
        items = self.selectedItems()
        for item in items:
            for x in range(column_count):
                widget = self.itemWidget(item, x)
                if widget:
                    self.removeItemWidget(item, x)
                    self.reparent_widgets[x] = widget
        super(Tree, self).startDrag(actions)

    def dropEvent(self, event):
        # Fix Mac/Maya drag and drop bug
        index = self.indexAt(event.pos())
        parent = index.parent()
        self.model().dropMimeData(
            event.mimeData(),
            event.dropAction(),
            index.row(),
            index.column(),
            parent
        )
        event.accept()
        # Re-create widget(s)
        pos = event.pos()
        item = self.itemAt(pos)
        for x in self.reparent_widgets.keys():
            self.setItemWidget(item, x, self.reparent_widgets[x])

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文