gpt4 book ai didi

python - pyside qtreewidget 约束拖放

转载 作者:太空狗 更新时间:2023-10-30 00:07:21 28 4
gpt4 key购买 nike

我正在尝试向 QTreeWidget 拖放功能添加约束,以防止分支进入另一个根中的另一个分支。

下面是一个让事情更清楚的例子:
我有 4 个对象。让我们称它们为苹果、香蕉、胡萝卜、榴莲吧。

树看起来像这样:

isDelicious (Root)
|-- BackgroundObjects (Branch)
|-- Durian
|-- ForgroundObjects (Branch)
|-- Apple
|-- Banana
|-- Carrot
isSmelly (Root)
|-- BackgroundObjects (Branch)
|-- Apple
|-- Carrot
|-- ForgroundObjects (Branch)
|-- Banana
|-- Durian

因此,允许将对象从 BackgroundObjects 拖放到 ForgroundObjects,反之亦然,但不允许将它们拖放到不同根的分支上。

我已尝试重新实现 dragMoveEvent、dragEnterEvent 和 dropEvent 并对其进行子类化,如果我在 dragEnterEvent 中对事件调用 accept,它会在之后调用 dragMoveEvent(这是我所期望的)。但是,仅当我在 QTreeWidget 之外放置时才会调用 dropEvent。

我想做的是在移动之前检查所选对象的祖 parent ,以及建议的新祖 parent ,看看它们是否相同。如果是这样,则接受此举。否则忽略移动。

我已经搜索过是否有任何答案,但到目前为止我还没有看到任何我正在尝试做的事情。最接近的可能是 Stack Overflow 中的这两个问题:
https://stackoverflow.com/questions/17134289/managing-drag-and-drop-within-qtreewidgets-in-pyside
qt: QTreeView - limit drag and drop to only happen within a particlar grandparent (ancestor)

最佳答案

Qt 似乎并没有使这类事情变得很容易。

我能想到的最好办法是在拖动进入和拖动移动事件期间临时重置项目标志。下面的示例动态计算当前顶级项目以限制拖放。但也可以通过使用 setData() 为每个项目添加标识符来完成。

from PyQt4 import QtCore, QtGui

class TreeWidget(QtGui.QTreeWidget):
def __init__(self, parent=None):
QtGui.QTreeWidget.__init__(self, parent)
self.setDragDropMode(self.InternalMove)
self.setDragEnabled(True)
self.setDropIndicatorShown(True)
self._dragroot = self.itemRootIndex()

def itemRootIndex(self, item=None):
root = self.invisibleRootItem()
while item is not None:
item = item.parent()
if item is not None:
root = item
return QtCore.QPersistentModelIndex(
self.indexFromItem(root))

def startDrag(self, actions):
items = self.selectedItems()
self._dragroot = self.itemRootIndex(items and items[0])
QtGui.QTreeWidget.startDrag(self, actions)

def dragEnterEvent(self, event):
self._drag_event(event, True)

def dragMoveEvent(self, event):
self._drag_event(event, False)

def _drag_event(self, event, enter=True):
items = []
disable = False
item = self.itemAt(event.pos())
if item is not None:
disable = self._dragroot != self.itemRootIndex(item)
if not disable:
rect = self.visualItemRect(item)
if event.pos().x() < rect.x():
disable = True
if disable:
for item in item, item.parent():
if item is not None:
flags = item.flags()
item.setFlags(flags & ~QtCore.Qt.ItemIsDropEnabled)
items.append((item, flags))
if enter:
QtGui.QTreeWidget.dragEnterEvent(self, event)
else:
QtGui.QTreeWidget.dragMoveEvent(self, event)
for item, flags in items:
item.setFlags(flags)

class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.tree = TreeWidget(self)
self.tree.header().hide()
def add(root, *labels):
item = QtGui.QTreeWidgetItem(self.tree, [root])
item.setFlags(item.flags() &
~(QtCore.Qt.ItemIsDragEnabled |
QtCore.Qt.ItemIsDropEnabled))
for index, title in enumerate(
('BackgroundObjects', 'ForegroundObjects')):
subitem = QtGui.QTreeWidgetItem(item, [title])
subitem.setFlags(
subitem.flags() & ~QtCore.Qt.ItemIsDragEnabled)
for text in labels[index].split():
child = QtGui.QTreeWidgetItem(subitem, [text])
child.setFlags(
child.flags() & ~QtCore.Qt.ItemIsDropEnabled)
add('isDelicious', 'Durian', 'Apple Banana Carrot')
add('isSmelly', 'Apple Carrot', 'Banana Durian')
root = self.tree.invisibleRootItem()
root.setFlags(root.flags() & ~QtCore.Qt.ItemIsDropEnabled)
self.tree.expandAll()
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.tree)

if __name__ == '__main__':

import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 300, 300, 300)
window.show()
sys.exit(app.exec_())

关于python - pyside qtreewidget 约束拖放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20618044/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com