我正在QTableView中进行自定义拖放实现。当我拖动一个单元格并将其放在另一个单元格上时,我想根据拖动的内容和放置的位置手动更改模型中的某些数据。我怎样才能做到这一点?我一直在阅读所有Qt文档,但我完全迷失了,特别是使用拖放功能,似乎C ++到PyQt的转换有点不那么直观。
基本上我需要的是当我丢弃时我想知道最初拖动的细胞以及它们被丢弃的位置。我的困惑似乎与QMimeData有关。从拖拽开始时我可以看出,拖拽事件接收到正确的MIME数据,但我不知道如何在PyQt中获取它(过去我能用文本和网址做这种事情,但我'在项目视图中丢失了)。我还需要知道我要去哪里。我想我可以做一个“光标位置的项目”,但我认为这个数据已经存在于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_())