如何避免点头之交

2024-06-10 14:41:12 发布

您现在位置:Python中文网/ 问答频道 /正文

在我的QtreeView中,我使用“qstandarditemodel”来显示几个具有单独属性的项。我想避免这个项目将不会混合。e、 g.香蕉应该可以移动到蔬菜(同一儿童水平),但不能低于亚洲(较高水平),移动到亚洲-水果是可以的(同一儿童水平)

样品

我和.itemChanged一起工作过,但似乎已经很晚了。我需要一个信号在它将被丢弃之前,以及项目在它将被丢弃的地方。我试过eventFilter然后

event.type() == QtCore.QEvent.DragMove: 

但是,如何获取要删除的项的索引以确定它在同一子级中?你知道吗


Tags: 项目event属性信号地方样品水平儿童
2条回答

为了解决这个问题,我创建了一个自定义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

一个完整的例子可以在下面的link中找到

下面的更改允许在child行中移动项,但不允许在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()

相关问题 更多 >