python - Qt QTreeWidget 之间的拖放

标签 python pyqt pyqt4 pyqt5 qtreewidget

在我的 QT 应用程序中,我有两个 QTreeWidget A 和 B。

我想重写这两种行为的拖放功能:

  • 从 A 到 A 将所有子项的项目移动。
  • 从 B 到 A 复制所有子项的项目。

我认为在 dropEvent 函数中我有 event.source() 来获取源代码。

但是如何用标志来动态地改变移动或复制的功能呢?

有例子吗?

谢谢

最佳答案

为了执行此任务,我们必须区分该操作是来自自己还是另一个小部件,因为它被 dropEvent 方法覆盖,这会返回一个 QDropEvent 类型的事件> 具有返回执行操作的对象的方法 source():

def dropEvent(self, event):
    if event.source() == self:
        # move
    else:
        # copy
  • From A to A move items with all childrens.

每个QTreeWidgetItem都与其父级相关联,因此如果它移动到父级,子级也会移动。

if event.source() == self:
    event.setDropAction(Qt.MoveAction)
    QTreeWidget.dropEvent(self, event)
  • From B to A copy items with all childrens.

这是最复杂的任务,因为当 QTreeWidget 使用拖放时,它使用 mimetype x-qabstractitemmodeldatalist 来存储关联的行和列的信息项目的 QModelIndex 加上包含角色及其值的字典:

row_1 | column_1 | number of valid roles | role_1_1 | value_1_1 | ... | role_n_1 | value_n_1 | row_2 | column_2 | ...

因此,知道行和列就不可能获得该项目,因此也不可能获得您的 child ,因为您必须拥有父级。所以你应该寻找另一种策略,解决方案是创建一个新的mimetype,在其中保存再次获取项目所需的信息,唯一的方法是保存项目的行,然后保存父项的行,然后像这样父级的父级行,直到到达某个 topLevelItem

由于您已经拥有该项目,您可以访问您的 child 及其包含的信息。完整的实现如下所示:

class TreeWidget(QTreeWidget):
    customMimeType = "application/x-customTreeWidgetdata"

    def mimeTypes(self):
        mimetypes = QTreeWidget.mimeTypes(self)
        mimetypes.append(TreeWidget.customMimeType)
        return mimetypes

    def startDrag(self, supportedActions):
        drag = QDrag(self)
        mimedata = self.model().mimeData(self.selectedIndexes())

        encoded = QByteArray()
        stream = QDataStream(encoded, QIODevice.WriteOnly)
        self.encodeData(self.selectedItems(), stream)
        mimedata.setData(TreeWidget.customMimeType, encoded)

        drag.setMimeData(mimedata)
        drag.exec_(supportedActions)

    def dropEvent(self, event):
        if event.source() == self:
            event.setDropAction(Qt.MoveAction)
            QTreeWidget.dropEvent(self, event)
        elif isinstance(event.source(), QTreeWidget):
            if event.mimeData().hasFormat(TreeWidget.customMimeType):
                encoded = event.mimeData().data(TreeWidget.customMimeType)
                parent = self.itemAt(event.pos())
                items = self.decodeData(encoded, event.source())
                for it in items:
                    item = QTreeWidgetItem(parent)
                    self.fillItem(it, item)
                    self.fillItems(it, item)
                event.acceptProposedAction()

    def fillItem(self, inItem, outItem):
        for col in range(inItem.columnCount()):
            for key in range(Qt.UserRole):
                role = Qt.ItemDataRole(key)
                outItem.setData(col, role, inItem.data(col, role))

    def fillItems(self, itFrom, itTo):
        for ix in range(itFrom.childCount()):
            it = QTreeWidgetItem(itTo)
            ch = itFrom.child(ix)
            self.fillItem(ch, it)
            self.fillItems(ch, it)

    def encodeData(self, items, stream):
        stream.writeInt32(len(items))
        for item in items:
            p = item
            rows = []
            while p is not None:
                rows.append(self.indexFromItem(p).row())
                p = p.parent()
            stream.writeInt32(len(rows))
            for row in reversed(rows):
                stream.writeInt32(row)
        return stream

    def decodeData(self, encoded, tree):
        items = []
        rows = []
        stream = QDataStream(encoded, QIODevice.ReadOnly)
        while not stream.atEnd():
            nItems = stream.readInt32()
            for i in range(nItems):
                path = stream.readInt32()
                row = []
                for j in range(path):
                    row.append(stream.readInt32())
                rows.append(row)

        for row in rows:
            it = tree.topLevelItem(row[0])
            for ix in row[1:]:
                it = it.child(ix)
            items.append(it)
        return items

如下link你会看到一个例子

关于python - Qt QTreeWidget 之间的拖放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47091216/

相关文章:

python - PyQt 自动调整 qlineedit 字符间距

python - 为什么 SLOT ('insertColumn()' ) 在 PyQt 绑定(bind)中失败?

php - 'page source' 的样子是否会影响性能

python - 为什么带参数的 object.__new__ 在 Python 2.x 中工作正常而不是在 Python 3.3+ 中工作?

qt4 - QT 小部件信号 - 综合列表?

python - QDateEdit.date().toString ("MMMM dd, yyyy") 不显示英文月份

python - 检查列表中的值是否等于某个数字

python - 从已在 pandas 中重新索引的数据透视表中选择一列

qt - 如何在 QWidget 中绘制简单的水平线?

qt - 如何在PyQt4中为QTreeWidget实现itemChecked和itemUnchecked信号?