python - 在多个 QTreeWidget 之间拖放数据

标签 python drag-and-drop pyside qtreewidget qtreewidgetitem

我有很多QTreeWidget。这里,有两棵树。 左边有“a”、“b”。 我想将这个项目拖到右边的树中。 我没有错误,但该项目变空了。 如何将左边的数据拖到右边的树上? 为什么?

数据是这样的。

b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x02\x00a\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x02\x00b'

from PySide import QtCore
from PySide import QtGui

import sys

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent=None)

        self.sequoia = Sequoia()
        self.baobab = Baobab()
        self.c_widget = QtGui.QWidget()
        h_boxlayout = QtGui.QHBoxLayout()
        h_boxlayout.addWidget(self.sequoia, 30)
        h_boxlayout.addWidget(self.baobab, 70)
        self.c_widget.setLayout(h_boxlayout)
        self.setCentralWidget(self.c_widget)
class Sequoia(QtGui.QTreeWidget):
    def __init__(self, parent=None):
        super(Sequoia, self).__init__(parent=None)
        self.setColumnCount(2)
        self.setAcceptDrops(True)
        self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
        self.sampleitem = QtGui.QTreeWidgetItem()

        self.sampleitem.setText(0, "a")
        self.sampleitem.setText(1, "b")
        self.addTopLevelItem(self.sampleitem)

class Baobab(QtGui.QTreeWidget):
    def __init__(self, parent=None):
        super(Baobab, self).__init__(parent=None)
        self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
        self.setColumnCount(2)
    def dragEnterEvent(self, event):
        if event.mimeData().hasFormat('application/x-qabstractitemmodeldatalist'):
            event.accept()
        return QtGui.QTreeWidget.dragEnterEvent(self, event)
    def dragMoveEvent(self, event):

        if event.mimeData().hasFormat('application/x-qabstractitemmodeldatalist') and not isinstance(event, QtGui.QDropEvent):
            event.accept()
        return QtGui.QTreeWidget.dragMoveEvent(self, event)
    def dropEvent(self, event):
        if event.mimeData().hasFormat('application/x-qabstractitemmodeldatalist'):    
            bytearray = event.mimeData().data('application/x-qabstractitemmodeldatalist')      
            datastream = QtCore.QDataStream(bytearray, QtCore.QIODevice.ReadOnly)
            print(3306, bytearray.data())       
            item = QtGui.QTreeWidgetItem()
            item.setFlags(QtCore.Qt.ItemFlag.ItemIsEditable|QtCore.Qt.ItemFlag.ItemIsEnabled|QtCore.Qt.ItemFlag.ItemIsSelectable|QtCore.Qt.ItemIsDragEnabled|QtCore.Qt.ItemIsDropEnabled)

            item.read(datastream)
            self.addTopLevelItem(item)
def main():
    try:
        QtGui.QApplication([])
    except Exception as e:
        print(e)

    mw = MainWindow()
    mw.show()
    sys.exit(QtGui.QApplication.exec_())
if __name__ == "__main__":
    main()

最佳答案

不需要在 QTreeWidget 中实现自己的拖放方法,只需正确配置即可:

from PySide import QtCore, QtGui

import sys


class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent=None)

        self.sequoia = Sequoia()
        self.baobab = Baobab()
        self.c_widget = QtGui.QWidget()
        h_boxlayout = QtGui.QHBoxLayout(self.c_widget)
        self.setCentralWidget(self.c_widget)
        h_boxlayout.addWidget(self.sequoia, 30)
        h_boxlayout.addWidget(self.baobab, 70)


class Sequoia(QtGui.QTreeWidget):
    def __init__(self, parent=None):
        super(Sequoia, self).__init__(parent=None)
        self.setColumnCount(2)
        self.setDefaultDropAction(QtCore.Qt.CopyAction)
        self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
        self.setAcceptDrops(True)

        self.sampleitem = QtGui.QTreeWidgetItem()
        self.sampleitem.setText(0, "a")
        self.sampleitem.setText(1, "b")
        self.addTopLevelItem(self.sampleitem)


class Baobab(QtGui.QTreeWidget):
    def __init__(self, parent=None):
        super(Baobab, self).__init__(parent=None)
        self.setColumnCount(2)
        self.setAcceptDrops(True)


def main():
    app = QtGui.QApplication(sys.argv)
    mw = MainWindow()
    mw.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

如果您仍然想手动实现它,那么如果我们使用您的观点,可能的解决方案是:

def dropEvent(self, event):
    if event.mimeData().hasFormat(
        "application/x-qabstractitemmodeldatalist"
    ):

        ba = event.mimeData().data(
            "application/x-qabstractitemmodeldatalist"
        )
        ds = QtCore.QDataStream(
            ba, QtCore.QIODevice.ReadOnly
        )
        i = 0

        item = QtGui.QTreeWidgetItem()
        while not ds.atEnd():
            row = ds.readInt32()
            column = ds.readInt32()
            map_items = ds.readInt32()
            self.addTopLevelItem(item)
            for _ in range(map_items):
                role = ds.readInt32()
                value = ds.readQVariant()
                item.setData(i, role, value)
            i = (i + 1) % self.columnCount()

但是上面是被迫的,更好的解决方案是使用模型的 dropMimeData 方法:

def dropEvent(self, event):
    if event.mimeData().hasFormat(
        "application/x-qabstractitemmodeldatalist"
    ):

        parent = self.indexAt(event.pos())
        self.model().dropMimeData(
            event.mimeData(), event.dropAction(), 0, 0, parent
        )

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

相关文章:

python - Pandas 集团 : apply a function with two arguments

python - Django 。在不影响其 updated_at 字段的情况下增加对象的查看次数

python - Django 表单字段验证错误消息如 "Please fill out this field"

html - native 拖放检查掉落项目的 id

python - 如何使用 QFileSystemWatcher 只发出一个directoryChanged 信号

python - pyside 显示/隐藏布局

python服务器http ://0. 0.0.0:8080/

拖动时的javascript鼠标悬停

html5 - 拖动 Canvas

python - PySide 中的自定义委托(delegate)