【问题标题】:Drag and Drop Data among multiple QTreeWidget在多个 QTreeWidget 之间拖放数据
【发布时间】:2019-06-04 12:59:19
【问题描述】:

我有多个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()

【问题讨论】:

    标签: python drag-and-drop pyside qtreewidget qtreewidgetitem


    【解决方案1】:

    在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
            )
    

    【讨论】:

    • 几乎完美。但是如果我不完全丢弃我的数据,则数据已被切碎......示例数据由第一个答案成功,但在我的实际代码中,第二个答案非常有帮助。但它有这样的问题。
    猜你喜欢
    • 2018-04-15
    • 1970-01-01
    • 2020-06-04
    • 2016-08-26
    • 2017-12-20
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    • 2014-01-04
    相关资源
    最近更新 更多