在多个 QTreeWidget 之间拖放数据
Drag and Drop Data among multiple QTreeWidget
我有很多 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中实现自己的drag-and-drop方法,只要正确配置即可:
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
)
我有很多 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中实现自己的drag-and-drop方法,只要正确配置即可:
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
)