PyQt项目视图自定义拖放 [英] PyQt item view custom drag and drop

查看:91
本文介绍了PyQt项目视图自定义拖放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am working on a custom drag-drop implementation in a QTableView. When I drag a cell and drop it on another cell I want to manually change some data in the model based on what was dragged and where it was dropped. How can I do this? I've been reading through all Qt documentation but I am utterly lost, and in particular with drag-drop it seems that the C++ to PyQt conversion is a little less intuitive.

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

Basically what I need is when I drop I want to know what cells were initially dragged, and where they were dropped. Where my confusion lies seems to be with QMimeData. From what I can tell when the drag starts, the drag event receives the right MIME data but I don't know how to get at it in PyQt (been able to do this sort of thing with text and urls in the past but I'm lost when it comes to an item view). I also need to know where I'm dropping to. I guess I could do an "item at cursor pos" but I assume this data already exists in the drop event and I just need to figure out how to query it.

这是一个简单的例子:

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:

You can not know where it was dragged since the mimeData does not have that information but you can get the data dragged, for that we created a temporary model where we will establish the mimeData emulating the same behavior of the drag. To obtain where it was dropped, the position that comes as part of the event must be used together with indexAt(), thus obtaining the 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_())

这篇关于PyQt项目视图自定义拖放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆