如何阻止QTreeWidget在拖放时创建重复项
下面的代码创建了一个包含五个项目的 QTreeWidget
。
这里的 self.setDragDropMode(self.InternalMove)
这个设置确保了当你把一个项目拖到另一个项目上时,不会生成它的副本(这样项目的数量始终保持不变)。
如果我们把这行代码换成 self.setDragDropMode(self.DragDrop)
,那么每次拖动/放下一个项目时,都会生成一个新的副本。
因为我不想在每次拖放事件中生成项目的副本,所以我希望使用 InternalMove
这个设置,但它又阻止了 QTreeWidget
接受来自其他地方的拖放(如果设置了 InternalMove
,QTreeWidget
就不允许从其他 QTreeWidget
、QListView 或文件浏览器中拖放)。
有没有办法设置一个覆盖,使得 QTreeWidget
不会创建拖动项目的副本,同时又能接受来自外部窗口的拖放呢?
from PyQt4 import QtCore, QtGui
app = QtGui.QApplication([])
class Tree(QtGui.QTreeWidget):
def __init__(self, *args, **kwargs):
super(Tree, self).__init__()
self.setDragEnabled(True)
self.setDropIndicatorShown(True)
self.setDragDropMode(self.InternalMove)
items=[QtGui.QTreeWidgetItem([name]) for name in ['Item_1','Item_2','Item_3','Item_4','Item_5']]
self.addTopLevelItems(items)
self.resize(360,240)
self.show()
tree=Tree()
sys.exit(app.exec_())
1 个回答
1
解决这个问题的关键在于,你需要在对象移动到下一个 QListsWidget
时进行处理,并检查数据是否重复。也就是说,要把数据从源位置移到目标位置,具体做法是先从源位置删除数据,然后再把这些数据添加到目标 QListsWidget
中。
你需要使用两个方法,分别是 dragEnterEvent
和 dropEvent
,来处理这些操作;
在
dragEnterEvent
方法中,检查要移动的对象是否在同一个QListsWidget
中。在
dropEvent
方法中,检查数据是否重复,并将数据从源位置移动到目标位置。
示例:
import sys
from PyQt4 import QtCore, QtGui
class QCustomTreeWidget (QtGui.QTreeWidget):
def __init__(self, parent = None):
super(QCustomTreeWidget, self).__init__(parent)
self.setDragEnabled(True)
self.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
self.resize(360,240)
def dragEnterEvent (self, eventQDragEnterEvent):
sourceQCustomTreeWidget = eventQDragEnterEvent.source()
if isinstance(sourceQCustomTreeWidget, QCustomTreeWidget):
if self != sourceQCustomTreeWidget:
sourceQCustomTreeWidget.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
eventQDragEnterEvent.accept()
else:
sourceQCustomTreeWidget.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
QtGui.QTreeWidget.dragEnterEvent(self, eventQDragEnterEvent)
else:
QtGui.QTreeWidget.dragEnterEvent(self, eventQDragEnterEvent)
def dropEvent (self, eventQDropEvent):
sourceQCustomTreeWidget = eventQDropEvent.source()
if isinstance(sourceQCustomTreeWidget, QCustomTreeWidget):
if self != sourceQCustomTreeWidget:
sourceQCustomTreeWidget.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
sourceQTreeWidgetItem = sourceQCustomTreeWidget.currentItem()
isFound = False
for column in range(0, self.columnCount()):
sourceQString = sourceQTreeWidgetItem.text(column)
listsFoundQTreeWidgetItem = self.findItems(sourceQString, QtCore.Qt.MatchExactly, column)
if listsFoundQTreeWidgetItem:
isFound = True
break
if not isFound:
(sourceQTreeWidgetItem.parent() or sourceQCustomTreeWidget.invisibleRootItem()).removeChild(sourceQTreeWidgetItem)
self.invisibleRootItem().addChild(sourceQTreeWidgetItem)
else:
sourceQCustomTreeWidget.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
QtGui.QTreeWidget.dropEvent(self, eventQDropEvent)
else:
QtGui.QTreeWidget.dropEvent(self, eventQDropEvent)
class QCustomQWidget (QtGui.QWidget):
def __init__ (self, parent = None):
super(QCustomQWidget, self).__init__(parent)
self.my1QCustomTreeWidget = QCustomTreeWidget(self)
self.my2QCustomTreeWidget = QCustomTreeWidget(self)
items = [QtGui.QTreeWidgetItem([name]) for name in ['Item_1', 'Item_2', 'Item_3', 'Item_4', 'Item_5']]
self.my1QCustomTreeWidget.addTopLevelItems(items)
self.allQHBoxLayout = QtGui.QHBoxLayout()
self.allQHBoxLayout.addWidget(self.my1QCustomTreeWidget)
self.allQHBoxLayout.addWidget(self.my2QCustomTreeWidget)
self.setLayout(self.allQHBoxLayout)
app = QtGui.QApplication([])
myQCustomQWidget = QCustomQWidget()
myQCustomQWidget.show()
sys.exit(app.exec_())