为什么 QTreeView 在拖放过程中不触发 Drop 或 Move 事件?

Why does QTreeView not fire a Drop or Move event during drag and drop?

我正试图找到 this 问题的答案,但我意识到我正在寻找的事件并没有发生。

import sys, new
from PyQt4 import QtGui, QtCore 

class MainForm(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainForm, self).__init__(parent)

        self.model = QtGui.QStandardItemModel()

        for k in range(0, 4):
            rootItem = self.model.invisibleRootItem()
            parentItem = QtGui.QStandardItem(QtCore.QString("Parent: %0").arg(k))
            for i in range(0, 5):
                item = QtGui.QStandardItem(QtCore.QString("Value: %0").arg(i))
                parentItem.appendRow(item)
            rootItem.appendRow(parentItem)

        self.view = QtGui.QTreeView()
        self.view.setModel(self.model)
        self.view.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
        self.view.expandAll()
        self.view.installEventFilter(self)
        self.setCentralWidget(self.view)


    def eventFilter(self, object, event):
        if object is self.view:
            if event.type() == QtCore.QEvent.Move:
                print "Moved!"
                event.accept()
                return True
            else:
                event.ignore()
                return super(MainForm, self).eventFilter(object, event)

def main():
    app = QtGui.QApplication(sys.argv)
    form = MainForm()
    form.show()
    app.exec_()

if __name__ == '__main__':
    main()

我解决该问题的想法是利用事件过滤器并监视 QtCore.QEvent.Move 事件。这是因为 DragDrop 模式设置为 QtGui.QAbstractItemView.InternalMove

The view accepts move (not copy) operations only from itself. - Documentation

问题是,此事件从未触发。 QtCore.QEvent.Drop 也不是。相反,我看到以下 events:

拖放成功。我可以按预期移动节点。 MoveDrop 事件发生了什么?

如果我取消勾选 if object is self.view 并只观察这两个事件,我仍然看不到它们发生。

您需要在视口上跟踪事件,并过滤 DragMoveDrop:

    self.view.viewport().installEventFilter(self)

def eventFilter(self, object, event):
    if object is self.view.viewport():
        if event.type() == QtCore.QEvent.DragMove:
            print "Moved!"
        elif event.type() == QtCore.QEvent.Drop:
            print "Dropped!"
    return super(MainForm, self).eventFilter(object, event)