代码之家  ›  专栏  ›  技术社区  ›  jpyams David Thompson

无重复元素的拖放

  •  1
  • jpyams David Thompson  · 技术社区  · 7 年前

    在Python 3的PyQt4中,如何访问被拖放到视图/模型中的数据?

    背景

    我正在与两个 QListView 我希望能够从第一个视图中拖动一个项目并将其放到第二个视图中。但是,列表必须保持唯一,因此删除已在列表中的项不会有任何作用。

    问题

    我不知道如何访问要删除的数据以验证它不在列表中。

    研究

    我找到了 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中的拖放数据呢?有没有办法解码 QimeData公司 什么东西?或者有其他方法检查掉的东西吗?

    更新

    这不是 this question . 我的问题是访问 QAbstractItemView / Qabstractem模型 ,而那个是关于PyQt中的基本拖放。答案不涉及如何从mimetype获取数据 'application/x-qabstractitemmodeldatalist' ,也不显示如何在 Qabstractem模型 .

    1 回复  |  直到 7 年前
        1
  •  0
  •   jpyams David Thompson    7 年前

    如果你想控制你的拖放行为,你需要设置你自己的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将调用 米米达塔() 对项目进行编码。在这里,我获取每个被拖动索引的项数据,将其放入列表中,通过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
    

    在第一行中,我从 QimeData公司 然后解码。然后,在 for 循环,检查目标视图中是否已存在某个项。如果是,请将其拆下。

    之后,代码的其余部分将确定在何处添加新行并插入新行。


    更多信息是 in the docs ,尤其是关于 adding new drag and drop types .