Search code examples
pythondrag-and-dropqt5pyqt5qlistwidget

Python PyQt5: QListWidget doesn't accept drops


I have tried to create a simple QListWidget that accepts text dropped into it. Can't make it to work. The drop-event doesn't even get triggered, the drag event is on the other hand. Can anybody point me in the right direction? What did I do wrong?

Thanks in advance.

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_())

Solution

  • By default, a QListWidget doesn't handle dropped text, so you have to reimplement the mime-data handling, like this:

    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)