Drag and drop with pyqt5 (SIGNAL)

2020-03-24 07:05发布

问题:

I am trying to get drag and drop (with images or files) working for my listwidget in pyqt5. I can find a lot of examples with pyqt4, but there is one part that does not work in the newer version:

In the "dropevent":

self.emit(QtCore.SIGNAL("dropped"), links)

and in the MainForm:

self.connect(self.view, QtCore.SIGNAL("dropped"), self.pictureDropped)

I read a lot of posts but can't seem to find an answer how this should be written down with pyqt5. Could anyone please help me with this?

link to the entire example: PyQT4: Drag and drop files into QListWidget

回答1:

Simple.

  1. The signal must come first
  2. The slot come as parameter.
  3. You must connect only after the signal was created
  4. You must emit only after the connection was made.

Here we go with a small example:

self.signalOwner.mySignal.connect(self.slotFunction)

In your example let's say and consider that the view owns the signal and that pictureDropped is your slot function, so:

self.view.dropped.connect(self.pictureDropped)

Remember, your signal must emit certain type(s) or nothing at all andddd your @pyqtSlot function must receive same type(s) with the function receiving the same amount of parameter that your signal emits.

I have made a post some short time ago about drag and drop with images, had many difficulties to figure it out how to accept events and how the classes behave, it's a bit deeper than only signals so, if you need here is the POST :D



回答2:

Your linked example uses the old-style signal and slot syntax, whereas you need to use the new-style syntax. In PyQt4 (versions 4.5 or later), you could use either style, but PyQt5 only supports the new style.

The old-style syntax allowed custom signals to be emitted on-the-fly, but the new-style syntax demands that the signal is declared beforehand on the class:

class ListWidget(QtWidgets.QListWidget):
    dropped = QtCore.pyqtSignal(list)

    def __init__(self, parent=None):
        ...

    def dropEvent(self, event):
        ...
        self.dropped.emit(list_of_files)

The signal connection is then made like this:

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        ...
        self.listWidget = ListWidget()
        self.listWidget.dropped.connect(self.handleDropped)

    def handleDropped(self, list_of_files):
        print('dropped:', list_of_files)