Python 如何避免掉在节点上
在我的Python 如何避免掉在节点上,python,pyqt,pyqt5,qstandarditemmodel,Python,Pyqt,Pyqt5,Qstandarditemmodel,在我的QtreeView中,我使用“QStandardItemModel”来显示具有单个属性的多个项目。我想避免该项目将不会混合。e、 g.香蕉应该可以移动到蔬菜(相同的儿童水平),但不低于亚洲(较高水平),移动到亚洲-水果是可以的(相同的儿童水平) 样品 我曾经使用过.itemChanged,但似乎很晚了。我需要一个信号,然后它将被删除,并且项目将被删除。我尝试了eventFilter并获得 event.type() == QtCore.QEvent.DragMove: 但是我如何获取项
QtreeView
中,我使用“QStandardItemModel”来显示具有单个属性的多个项目。我想避免该项目将不会混合。e、 g.香蕉应该可以移动到蔬菜(相同的儿童水平),但不低于亚洲(较高水平),移动到亚洲-水果是可以的(相同的儿童水平)
样品
我曾经使用过.itemChanged
,但似乎很晚了。我需要一个信号,然后它将被删除,并且项目将被删除。我尝试了eventFilter
并获得
event.type() == QtCore.QEvent.DragMove:
但是我如何获取项目的索引,在该索引中项目将被删除,以确定其是否处于同一子级?为了解决这个问题,我创建了一个自定义mimetype,它发送索引信息及其深度级别,它将只移动那些与目标的子级具有相同级别的索引
class TreeView(QTreeView):
customMimeType = "application/x-customqstandarditemmodeldatalist"
def __init__(self, *args, **kwargs):
QTreeView.__init__(self, *args, **kwargs)
self.setSelectionMode(QAbstractItemView.SingleSelection)
self.setDragEnabled(True)
self.viewport().setAcceptDrops(True)
self.setDropIndicatorShown(True)
self.setDragDropMode(QTreeView.InternalMove)
def itemsToPixmap(self, indexes):
rect = self.viewport().visibleRegion().boundingRect()
pixmap = QPixmap(rect.size())
pixmap.fill(Qt.transparent)
painter = QPainter(pixmap)
for index in indexes:
painter.drawPixmap(self.visualRect(index), self.viewport().grab(self.visualRect(index)))
return pixmap
def mimeTypes(self):
mimetypes = QTreeView.mimeTypes(self)
mimetypes.append(TreeView.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.selectedIndexes(), stream)
mimedata.setData(TreeView.customMimeType, encoded)
drag.setMimeData(mimedata)
px = self.itemsToPixmap(self.selectedIndexes())
drag.setPixmap(px)
drag.setHotSpot(self.viewport().mapFromGlobal(QCursor.pos()) - QPoint(self.horizontalOffset(),
self.verticalOffset()))
drag.exec_(supportedActions)
def encodeData(self, items, stream):
stream.writeInt32(len(items))
for item in items:
p = item
rows = []
while p.isValid():
rows.append(p.row())
p = p.parent()
stream.writeInt32(len(rows))
for row in reversed(rows):
stream.writeInt32(row)
def dropEvent(self, event):
if event.source() == self:
if event.mimeData().hasFormat(TreeView.customMimeType):
encoded = event.mimeData().data(TreeView.customMimeType)
items = self.decodeData(encoded, event.source())
ix = self.indexAt(event.pos())
current = self.model().itemFromIndex(ix)
p = current
level = 1
while p:
p = p.parent()
level += 1
for item, ilevel in items:
if level == ilevel:
item.parent().takeRow(item.row())
current.appendRow(item)
self.clearSelection()
event.acceptProposedAction()
else:
event.ignore()
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 = self.model().item(row[0])
for r in row[1:]:
it = it.child(r)
items.append((it, len(row)))
return items
下面是一个完整的示例,下面的更改允许在一行child中移动项目,但不允许将其移动到外部。如果目标不在同一级别,仍在更改光标
def dropEvent(self, event):
if event.source() == self:
if event.mimeData().hasFormat(TreeView.customMimeType):
encoded = event.mimeData().data(TreeView.customMimeType)
items = self.decodeData(encoded, event.source())
ix = self.indexAt(event.pos())
current = self.model().itemFromIndex(ix)
p = current
level = 0
while p:
p = p.parent()
level += 1
for item, ilevel in items:
if level == ilevel:
item.parent().takeRow(item.row())
current.parent().insertRow(current.row(),item)
self.clearSelection()
event.acceptProposedAction()
else:
event.ignore()
我在子类化方面遇到了问题,因为我使用了
loadUIC
,通过复制设置(高度、宽度)来解决。但最重要的是,我没有找到一个解决方案,因为不再可能对条目进行排序。我尝试了current.insertRow(current.row(),item)
,但它将其作为第一个子项插入level
和ìlevel`是不同的,所以肯定还有其他东西……如果你通过Qt设计器创建了一个QTreeView,那么只需升级它以使用我的类。我通过self.structureTreeModel=TreeModel()
分配它,但它在我的窗口中显示为额外的小部件。你必须升级你的QTreeWidget,请检查以下链接:我确实检查了,最后一个链接断了。所以我到处玩,最后没有收到错误信息。但是TreeView要么不可见,要么位于左上角,要么位于QtreeView小部件内部。我做了链接中提到的事情。