Qt拖放不适用于自定义项目

问题描述

我正在使用pyside2(Qt5)和自定义树视图小部件(MyTreeView,继承自QTreeView)来构建GUI。该模型是QStandardItemmodel对象,而项目是自定义的:MyStandardItem,继承自QStandardItem

问题是:如果在执行拖放操作后检查移动项目的类型,则该项目已变成QStandardItem,但应该是MyStandardItem 。 我相信问题出在 MimeType 上,经过大量研究,我发现解决方案可能是创建自定义模型并覆盖MIME相关功能。 我试图找出方法,但我做不到。

所以,这是问题:

对于它的价值,这是MyStandardItem的实现:

class MyStandardItem(QStandardItem):
    def __init__(self,text,font,icon_path='',value='',num=0,check_state=None):
        super().__init__()
        self.setDragEnabled(True)
        self.setDropEnabled(True)
        self.setText(text)
        self.setData({'value': (value,num)})
        self.setToolTip(str(self.data()['value']))
        self.setFont(font)
        self.setIcon(QIcon(icon_path))
        self.toggled = check_state
        if check_state is not None:
            self.setCheckable(True)
            self.setCheckState(check_state)

    def setCheckState(self,checkState):
        super().setCheckState(checkState)
        if checkState == Qt.Unchecked:
            self.toggled = Qt.Unchecked
        else:
            self.toggled = Qt.Checked

解决方法

我找到了无需创建自定义模型即可解决此问题的方法。

MyTreeView.dropEvent函数中:我没有调用super().dropEvent()来完成拖放操作,而是由我自己实现的,方法是将项目的数据复制到变量中并创建一个 new MyStandardItem从这些数据中。然后,我调用insertRow()将新项目插入给定位置,并调用deleteRow()删除旧项目。 显然,移动的项目必须在操作(DragEnterEvent())开始时存储在class属性中。 一切正常。

PS:我之前已经尝试过这种方法,但是我总是以空行结尾。区别在于,我创建了一个新项目,而不是重新插入旧项目。

这是我的代码的某些部分,以澄清我的意思。请注意,这些函数是MyTreeView的方法。

def dragEnterEvent(self,event: QDragEnterEvent):
    if event.source() == self:
        self.dragged_item = self.model.itemFromIndex(self.selectionModel().selectedIndexes()[0])
        super().dragEnterEvent(event)
    else:
        ...


def dropEvent(self,event: QDropEvent):
    index = self.indexAt(event.pos())
    if not index.isValid():
        return
    over_item = self.model.itemFromIndex(index)
    over_value = over_item.data()['value'][0]
    if event.source() == self:
        item_was_moved = self._move_item(over_value,over_parent_value)
        if not item_was_moved:
            return
    else:
        ...


def _move_item(self,over_value,over_parent_value):
    over_value = self._check_indicator_position(over_value)
    if over_value is None:
        return False
    dragged_parent_value = self.dragged_item.parent().data()['value'][0]
    dragged_value = self.dragged_item.data()['value'][0]
    row = self.dragged_item.row()
    items = guifunc.copy_row_items(self.dragged_item,row)
    over_value_num = int(over_value.strip('test'))
    self.dragged_item.parent().insertRow(over_value_num,items)
    if over_value_num < row:
        row += 1
    self.dragged_item.parent().removeRow(row)
    return True