Python PyQt5:QListWidget 不接受放置

Python PyQt5: QListWidget doesn't accept drops

我试图创建一个简单的 QListWidget,它接受放入其中的文本。无法正常工作。 drop 事件甚至不会被触发,drag 事件是另一方面。 有人能指出我正确的方向吗?我做错了什么?

提前致谢。

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton,  QLineEdit, QLabel, QListWidget
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot

class App(QWidget):

    def __init__(self):
        super().__init__()
        self.title = 'PyQt5 drag and drop'
        self.left = 500
        self.top = 400
        self.width = 400
        self.height = 250
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        editBox = QLineEdit('Drag this', self)
        editBox.setDragEnabled(True)
        editBox.move(10, 10)
        editBox.resize(100,32)

        listwidget = CustomLabel(self)
        listwidget.move(130,15)

        self.show()


class CustomLabel(QListWidget):

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

    def dragEnterEvent(self, e):
        if e.mimeData().hasFormat('text/plain'):
            print("dragged")
            e.accept()
        else:
            e.ignore()


    def dropEvent(self, e):
        print("dropped")

        self.addItem(event.mimeData().text())

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

看起来你的代码是基于 this example.

主要区别在于您的 CustomLabel 继承自 QListWidget 而不是 QLabel。不幸的是,QListWidget 继承自 QAbstractScrollArea,它是与该滚动区域关联的视口小部件,它将接收各种 drag/drop 事件——而不是 QListWidget 本身。

您最好的选择可能是在视口上安装一个事件过滤器....

class CustomLabel(QListWidget):
    def __init__(self, parent):
        super().__init__(parent)
        self.setAcceptDrops(True)

        # Install the event filter.
        self.viewport().installEventFilter(self)

    def dragEnterEvent(self, e):
        if e.mimeData().hasFormat('text/plain'):
            print("dragged")
            e.accept()
        else:
            e.ignore()

    def eventFilter (self, obj, event):
        if obj == self.viewport():
            print("event")
            if event.type() == QEvent.DragMove:
                print("moved")
                event.accept()

                # Your drag enter event processing code goes here
                return True
            if event.type() == QEvent.Drop:
                print("dropped")
                event.accept()

                # Your drop event processing code goes here
                return True
        return super(CustomLabel, self).eventFilter(obj, event)

编辑 1:

您可能还需要添加...

from PyQt5.QtCore import QEvent

默认情况下,QListWidget 不处理丢失的文本,因此您必须重新实现 mime 数据处理,如下所示:

class CustomLabel(QListWidget):    
    def __init__(self, parent):
        super().__init__(parent)
        self.setAcceptDrops(True)

    def mimeTypes(self):
        mimetypes = super().mimeTypes()
        mimetypes.append('text/plain')
        return mimetypes

    def dropMimeData(self, index, data, action):
        if data.hasText():
            self.addItem(data.text())
            return True
        else:
            return super().dropMimeData(index, data, action)

太棒了。现在可以了。 非常感谢你的帮助。 这就是全部代码:

import sys
from PyQt5.QtWidgets import QApplication, QWidget,  QLineEdit, QListWidget


class App(QWidget):

    def __init__(self):
        super().__init__()
        self.title = 'PyQt5 drag and drop'
        self.left = 500
        self.top = 400
        self.width = 400
        self.height = 250
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        editBox = QLineEdit('Drag this', self)
        editBox.setDragEnabled(True)
        editBox.move(10, 10)
        editBox.resize(100,32)

        listwidget = CustomList(self)
        listwidget.move(130,15)

        self.show()


class CustomList(QListWidget):

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

    def mimeTypes(self):
        mimetypes = super().mimeTypes()
        mimetypes.append('text/plain')
        return mimetypes

    def dropMimeData(self, index, data, action):
        if data.hasText():
            self.addItem(data.text())
            return True
        else:
            return super().dropMimeData(index, data, action)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())