【问题标题】:How to make drag and drop from QListWidget to QLabel in PyQt如何在 PyQt 中从 QListWidget 拖放到 QLabel
【发布时间】:2021-08-12 20:22:27
【问题描述】:

在我使用 PyQt 编写的应用程序中,我想通过将项目从 QListWidget 拖放到 QLabel 来执行拖放功能(根据 QListWidget 中项目的文本在 QLabel 上设置文本)。为了做到这一点,我创建了继承表单 QLabel 的新类以添加 dragEnterEvent 和 dropEvent。我的标签代码:

class Label(QLabel):
  def __init__(self, parent):
    super(Label, self).__init__(parent)
    self.setAcceptDrops(True)

  def dragEnterEvent(self, event):
    print('drag')
    print(event.mimeData().text())
    if event.mimeData().hasText():
        event.accept()
    else:
        event.ignore()

  def dropEvent(self, event):
    print('drop')
    self.setText(event.mimeData().text())

问题是当我从 QListWidget 拖动项目时它没有文本,所以我的代码不起作用。据我了解,这是因为当我从 QListWidget 拖动项目时,我不是在拖动文本,而是整个小部件(因为据我了解,列表中的项目不是字符串,而是 QListWidgetItem)。根据我在这里发现的不同问题,我想我也应该为拖动的项目创建一个新类,但此时我不知道是否应该为 QListWidget 或 QListWidgetItem 做。或者也许我应该以完全不同的方式做到这一点?

【问题讨论】:

    标签: python pyqt


    【解决方案1】:

    从 Qt 项目视图中拖动时,您不是在“拖动小部件”,而是选择的序列化表示。

    该表示以application/x-qabstractitemmodeldatalist mime 格式存储,为了读取其内容,您必须使用 QDataStream。

    对于每个项目,存储的数据是:

    • 项目行
    • 项目列
    • 对于数据大小范围内的每个条目(有多少角色/值对):
      • 角色
      • 价值

    此数据必须始终以上述结构读取,您不能“跳过”任何部分,否则数据将无法正确读取,因为它存储在“序列化”流中。

    因此,您可以通过以下方式实现:

    class Label(QLabel):
        def __init__(self, parent):
            super(Label, self).__init__(parent)
            self.setAcceptDrops(True)
    
        def dragEnterEvent(self, event):
            mime = event.mimeData()
            if (mime.hasText() or 
                mime.hasFormat('application/x-qabstractitemmodeldatalist')):
                    event.accept()
            else:
                event.ignore()
    
        def dropEvent(self, event):
            mime = event.mimeData()
            if mime.hasText():
                self.setText(mime.text())
            elif mime.hasFormat('application/x-qabstractitemmodeldatalist'):
                textList = []
                stream = QDataStream(mime.data('application/x-qabstractitemmodeldatalist'))
                while not stream.atEnd():
                    # we're not using row and columns, but we *must* read them
                    row = stream.readInt()
                    col = stream.readInt()
                    for dataSize in range(stream.readInt()):
                        role, value = stream.readInt(), stream.readQVariant()
                        if role == Qt.DisplayRole:
                            textList.append(value)
                self.setText(', '.join(textList))
    

    【讨论】:

      猜你喜欢
      • 2020-12-29
      • 2019-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-03
      • 1970-01-01
      • 2018-07-06
      相关资源
      最近更新 更多