QTreeView 具有可重新排序的元素,但元素应该位于同一父文件夹中

问题描述 投票:0回答:1

我正在使用 PyQt6。 我想要一个带有可重新排序元素的 QTreeview。 但元素只能在比原来更深的同一层次结构中移动,就像在这张图片中一样,项目“A1”只能在文件夹“AAA”中重新排序

正如我所想,我可以通过

dragMoveEvent
实现,当光标显示“放入”工具提示时,我可以取消操作 - 但我没有找到相应的值来获取光标。

有人有同样的问题吗

这是代码:

class TreeViewWithReorder(QTreeView):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Tree View with Reorderable Functionality")
        self.resize(600, 400)

        # Create a QStandardItemModel
        self.model = QStandardItemModel()

        # Create a root item
        root_item = QStandardItem('AAA')
        root_item_2 = QStandardItem('BBB')

        # Create child items
        technician1 = QStandardItem('A1')
        technician2 = QStandardItem('A2')
        technician3 = QStandardItem('A3')

        technician4 = QStandardItem('B1')
        technician5 = QStandardItem('B2')

        # Add child items to the root items
        root_item.appendRow(technician1)
        root_item.appendRow(technician2)
        root_item.appendRow(technician3)

        root_item_2.appendRow(technician4)
        root_item_2.appendRow(technician5)

        # Set the model's root items
        self.model.appendRow(root_item)
        self.model.appendRow(root_item_2)

        self.setModel(self.model)
        self.setDragEnabled(True)
        self.setAcceptDrops(True)
        self.setDragDropMode(QTreeView.DragDropMode.InternalMove)

    def dragMoveEvent(self, event):
        super().dragMoveEvent(event)
pyqt pyqt6 qtreeview
1个回答
0
投票

您需要检查放置事件的可能目标是否与拖动的项目是同一个父级。

一种可能性如下:

    def dragMoveEvent(self, event):
        if event.source() != self:
            event.ignore()
            return
        super().dragMoveEvent(event)
        index = self.selectedIndexes()[0]
        target = self.indexAt(event.pos())
        if index.parent() == target or not event.isAccepted():
            return
        elif (
            target.parent() != index.parent()
            or self.dropIndicatorPosition() == self.DropIndicatorPosition.OnItem
        ):
            event.ignore()

程序如下:

  • 获取当前选中的item,这里假设是被拖动的item;
  • 获取鼠标下的模型索引,也就是最终会落下的位置;
  • 调用基础实现,最终接受或拒绝事件;
  • 如果目标是父级,我们继续默认行为;
  • 如果目标父项与拖动的索引相同,则意味着我们要在同一个父项中放置,但我们需要确保我们不会尝试放置在子项上;如果上述情况均不成立,我们将忽略该事件,因此不可能进行丢弃;

请注意,您应始终确保项目具有正确的拖/放标志。例如,根项目不应该是可拖动的,并且子项目可能不应该允许放在它们上面,否则它们也会成为父项目。

在您的情况下,对于基本的单层结构,您可以在

__init__
中执行以下操作:

        for pr in range(self.model.rowCount()):
            parent = self.model.item(pr)
            parent.setFlags(parent.flags() & ~Qt.ItemFlag.ItemIsDragEnabled)
            for cr in range(parent.rowCount()):
                child = parent.child(cr)
                child.setFlags(child.flags() & ~Qt.ItemFlag.ItemIsDropEnabled)

如果您的结构有多于一层,那么您最终应该仅针对 can 有子项的项目更改上述标志,因此您还需要在上面的

dragMoveEvent()
中进行检查。

© www.soinside.com 2019 - 2024. All rights reserved.