在我的 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/