【问题标题】:How to detect that an item in a QStandardItemModel is dropped onto another?如何检测 QStandardItemModel 中的一个项目被放到另一个项目上?
【发布时间】:2015-01-16 17:55:48
【问题描述】:

我如何接收QStandardItem 被拖放到另一个 QStandardItem 上的通知,从而成为后者的子项?

我认为我可以通过重新实现 QStandardItemModel.moveRows 来做到这一点,但它不会在 drop 后被调用 :( 下面是我正在尝试做的一个示例。要测试,运行程序并删除一个将树视图中的项目移到另一个上。如果它有效,您应该会在控制台中看到确认 moveRows 已被调用。

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *


class Model(QStandardItemModel):
    def moveRows(
            self, source_parent, source_row, count, destination_parent,
            destination_child):
        print(
            'Moving {} row(s) from row {} of parent {} to row {} of parent {}'
            .format(
                count, source_row, source_parent, destination_child,
                destination_parent)
        )
        super().moveRows(
            source_parent, source_row, count, destination_parent,
            destination_child)
        return True


def _create_item(text):
    item = QStandardItem(text)
    flags = Qt.ItemIsDragEnabled | Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsDropEnabled
    item.setFlags(flags)
    return item


model = Model()
model.appendRow([_create_item('Item 1')])
model.appendRow([_create_item('Item 2')])

app = QApplication([])
view = QTreeView()
view.setDragDropMode(view.InternalMove)
view.setModel(model)
view.show()
app.exec_()

【问题讨论】:

    标签: qt python-3.x drag-and-drop pyqt pyqt5


    【解决方案1】:

    通过研究 QStandardItemModel 源代码,我意识到必须覆盖 QAbstractItemModel.dropMimeData,才能对物品掉落做出反应。 QStandardItemModel 在其dropMimeData 的实现中移动项目,但以子类无法挂钩的方式移动项目,因此您必须自己处理dropMimeData

    这是我基于dropMimeData 的解决方案,项目表示作为 Python 泡菜包含在 MIME 数据中:

    import pickle
    from PyQt5.QtGui import *
    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *
    
    
    _mimeType = 'application/x-standarditemmodeldatalist'
    
    
    class Model(QStandardItemModel):
        def dropMimeData(
                self, data, action, row, column, parent):
            # Access parent before calling super implementation, because it may mutate parent
            dest_str = 'parent {}'.format(parent.data(Qt.DisplayRole)) if \
                parent.isValid() else 'root'
    
            ret_val = super().dropMimeData(data, action, row, column, parent)
            if action != Qt.MoveAction or not data.hasFormat(_mimeType):
                return ret_val
    
            item_data = pickle.loads(data.data(_mimeType))[0]
            print('Moving {} to {}'.format(item_data, dest_str))
            return True
    
        # Override in order to add custom MIME data
        def mimeData(self, indexes):
            mimeData = super().mimeData(indexes)
            data = [index.data(Qt.DisplayRole) for index in indexes]
            mimeData.setData(_mimeType, pickle.dumps(data))
    
            return mimeData
    
        # Override in order to announce our custom MIME type
        def mimeTypes(self):
            return super().mimeTypes() + [_mimeType]
    
    
    def _create_item(text):
        item = QStandardItem(text)
        flags = Qt.ItemIsDragEnabled | Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsDropEnabled
        item.setFlags(flags)
        return item
    
    
    model = Model()
    model.appendRow([_create_item('Item 1')])
    model.appendRow([_create_item('Item 2')])
    
    app = QApplication([])
    view = QTreeView()
    view.setDragDropMode(view.InternalMove)
    view.setModel(model)
    view.show()
    app.exec_()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-26
      • 1970-01-01
      • 2016-04-15
      • 2012-12-25
      • 1970-01-01
      • 2018-07-28
      • 2020-02-06
      • 1970-01-01
      相关资源
      最近更新 更多