PyQt项目视图自定义拖放

斯宾塞

我正在研究QTableView中的自定义拖放实现。当我将一个单元格拖放到另一个单元格上时,我想根据所拖动的内容和放置的位置手动更改模型中的某些数据。我怎样才能做到这一点?我一直在阅读所有Qt文档,但完全迷失了方向,尤其是通过拖放操作,似乎C ++到PyQt的转换不太直观。

基本上,我需要的是在放下时想知道最初拖动了哪些单元格以及将它们放到哪里。我困惑的地方似乎在于QMimeData。从我可以知道什么时候开始拖动开始,拖动事件接收到正确的MIME数据,但是我不知道如何在PyQt中使用它(过去可以使用文本和url进行这种操作,但是我会丢失有关项目视图的信息)。我还需要知道我要去的地方。我想我可以做一个“游标pos处的项目”,但是我假设这个数据已经存在于drop事件中,我只需要弄清楚如何查询它。

这是一个简单的例子:

import sys
from PyQt4 import QtGui, QtCore


class TableView(QtGui.QTableView):
     def __init__(self, parent=None):
         QtGui.QTreeWidget.__init__(self, parent)
         self.setDragEnabled(True)
         self.setDropIndicatorShow(True)
         self.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
         self.setDragDropOverwriteMode(False)
         self.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)

     def dragEnterEvent(self, event):
        event.accept()

    def dropEvent(self, event):
        # I want to do cool things with the dragged cells, and I need to know where they dropped!
        print(event.mimeData().formats()) # this tells me that I shuld get some sort of "qabstractitemmodeldatalist". Sounds promising...
        print(event.mimeData().data("application/x-qabstractitemmodeldatalist")) # this gives me an interesting looking QByteArray but I have no idea what to do with it...
        event.accept()

class Dialog(QtGui.QDialog):
    def __init__(self):
        super(Dialog, self).__init__()

        model = QtGui.QStandardItemModel(self)
        model.insertRow(0, QtGui.QStandardItem("C"))
        model.insertRow(0, QtGui.QStandardItem("B"))
        model.insertRow(0, QtGui.QStandardItem("A"))

        table = TableView(self)
        table.setModel(model)

app = QtGui.QApplication(sys.argv)
ex = Dialog()
ex.show()
sys.exit(app.exec_())
永乐

您不知道将其拖到何处,因为mimeData没有该信息,但是您可以将数据拖到其中,为此,我们创建了一个临时模型,在该模型中,我们将建立mimeData以模拟拖动的相同行为。为了获得放置位置,必须将与事件一起出现的位置与indexAt()一起使用,从而获得QModelIndex:

import sys
from PyQt4 import QtGui, QtCore


class TableView(QtGui.QTableView):
    def __init__(self, parent=None):
        QtGui.QTreeWidget.__init__(self, parent)
        self.setDragEnabled(True)
        self.setDropIndicatorShown(True)
        self.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
        self.setDragDropOverwriteMode(False)
        self.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)

    def dragEnterEvent(self, event):
        event.accept()

    def dropEvent(self, event):
        if self.viewport().rect().contains(event.pos()):
            fake_model = QtGui.QStandardItemModel()
            fake_model.dropMimeData(
                event.mimeData(), event.dropAction(), 0, 0, QtCore.QModelIndex()
            )
            print("from:")
            for r in range(fake_model.rowCount()):
                for c in range(fake_model.columnCount()):
                    ix = fake_model.index(r, c)
                    print(ix.data())
            to_index = self.indexAt(event.pos())
            if to_index.isValid():
                print("to:", to_index.data())
        super(TableView, self).dropEvent(event)


class Dialog(QtGui.QDialog):
    def __init__(self):
        super(Dialog, self).__init__()

        model = QtGui.QStandardItemModel(self)
        for letter in "ABC":
            model.appendRow(QtGui.QStandardItem(letter))

        table = TableView()
        table.setModel(model)

        lay = QtGui.QVBoxLayout(self)
        lay.addWidget(table)


if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    ex = Dialog()
    ex.show()
    sys.exit(app.exec_())

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章