没有重复元素的拖放
Drag and Drop without duplicate elements
在带有 Python 3 的 PyQt4 中,如何访问被拖放到 view/model 中的数据?
背景
我正在构建一个包含两个 QListView
的界面。我希望能够将一个项目从第一个视图拖放到第二个视图中。但是,该列表需要保持唯一性,因此删除已经在列表中的项目应该没有任何作用。
问题
我无法弄清楚如何访问被删除的数据以验证它不在列表中。
研究
我找到了 QAbstractItemModel
方法 dropMimeData()
,它应该 return 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, but in Python 3 I cannot create a QVariant
object (per 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
当有人从列表中抓取并拖动 item/items 时,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, particularly the section about adding new drag and drop types。
在带有 Python 3 的 PyQt4 中,如何访问被拖放到 view/model 中的数据?
背景
我正在构建一个包含两个 QListView
的界面。我希望能够将一个项目从第一个视图拖放到第二个视图中。但是,该列表需要保持唯一性,因此删除已经在列表中的项目应该没有任何作用。
问题
我无法弄清楚如何访问被删除的数据以验证它不在列表中。
研究
我找到了 QAbstractItemModel
方法 dropMimeData()
,它应该 return 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, but in Python 3 I cannot create a QVariant
object (per 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
当有人从列表中抓取并拖动 item/items 时,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, particularly the section about adding new drag and drop types。