在使用Python 3的PyQt4中,如何访问拖放到视图/模型中的数据?
我正在建立一个有两个QListView
s的界面。我希望能够从第一个视图中拖动一个项目并将其放到第二个视图中。但是,列表需要保持唯一,因此删除列表中已有的项目应该不执行任何操作。
我无法弄清楚如何访问被删除的数据以验证它是否已经在列表中。
我找到了QAbstractItemModel
方法dropMimeData()
,它应该返回True
接受丢弃的数据,并且False
拒绝它。但是,拖放数据在QMimeData
中,它的类型为application/x-qabstractitemmodeldatalist
。离开the docs,我试图解码数据:
def dropMimeData(self, data, action, row, column, parent=None):
stream = QtCore.QDataStream(data.data('application/x-qabstractitemmodeldatalist'))
text = ''
while not stream.atEnd():
stream >> text
print(text)
但是,如果我运行它,我会得到
stream >> text
ValueError: string of length 1 expected
如果我设置text = 'a'
,那么a
就会反复打印。
我尝试了this solution,但在Python 3中我无法创建一个QVariant
对象(根据this answer)。
那么如何在PyQt中访问拖放数据呢?有没有办法解码QMimeData
的东西?或者还有另一种方法可以检查掉落的内容吗?
这不是this question的副本。我的问题是访问QAbstractItemView
/ QAbstractItemModel
中丢弃的数据,而那个是关于PyQt中的基本拖放。答案没有解决如何从mimetype 'application/x-qabstractitemmodeldatalist'
获取数据,也没有说明如何防止QAbstractItemModel
中的重复。
如果要控制拖放行为,则需要设置自己的mime数据。
您可以根据需要对要拖放的数据进行编码。我将把拖动的项目放入列表并将它们编码为JSON,因为我很懒。
在源视图的模型中,覆盖mimeTypes()
和mimeData()
:
def mimeTypes(self):
return ['text/json']
def mimeData(self, indexes):
dragData = json.dumps([index.data() for index in indexes])
mimeData = QtCore.QMimeData()
mimeData.setData('text/json', dragData)
return mimeData
当有人从列表中抓取并拖动项目/项目时,Qt将调用mimeData()
对项目进行编码。在这里,我获取拖动的每个索引的项数据,将其放入列表,通过JSON将列表转换为字符串,并将该JSON添加到QMimeData
。
在mimeTypes()
中,我指定mime数据将包含JSON数据。
在目标视图的模型中,覆盖dropMimeData()
:
def dropMimeData(self, data, action, row, column, parent=None):
dropData = json.loads(bytes(data.data('text/json')))
for item in dropData:
if item in self.stringList():
self.removeRow(self.stringList().index(item))
if row != -1:
beginRow = row
elif parent:
beginRow = parent.row()
else:
beginRow = self.rowCount()
self.insertRows(beginRow, len(dropData))
for i, item in enumerate(dropData):
self.setData(self.index(beginRow+i, 0), item)
return True
在第一行中,我从QMimeData
中获取JSON数据并对其进行解码。然后,在for
循环中,我检查其中一个项目是否已经在目标视图中。如果是这样,请将其删除。
之后,其余代码确定添加新行的位置并插入它们。
更多信息是in the docs,特别是关于adding new drag and drop types的部分。