function of pyqtSlot

Kester picture Kester · Aug 23, 2017 · Viewed 21.4k times · Source

I just read a tutorial about pyqt5 button from here. And the code is as below. There is a question about button.clicked.connect(self.on_click) and @pyqtSlot(). If I delete @pyqtSlot() from the code, it still works. However, the button does not work if I delete button.clicked.connect(self.on_click) from the code. So what is the function of @pyqtSlot() in this code?

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

class App(QWidget):

    def __init__(self):
        super().__init__()
        self.title = 'PyQt5 button - pythonspot.com'
        self.left = 10
        self.top = 10
        self.width = 320
        self.height = 200
        self.initUI()

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

        button = QPushButton('PyQt5 button', self)
        button.setToolTip('This is an example button')
        button.move(100,70) 
        button.clicked.connect(self.on_click)

        self.show()

    @pyqtSlot()
    def on_click(self):
        print('PyQt5 button click')

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

Answer

9dogs picture 9dogs · Aug 23, 2017

button.clicked.connect(self.on_click) binds signal of a button (clicked) to a slot self.on_click. Without this binding click will result in no action.

@pyqtSlot, in turn, is a decorator which converts simple python method to Qt slot. Doc states:

Although PyQt5 allows any Python callable to be used as a slot when connecting signals, it is sometimes necessary to explicitly mark a Python method as being a Qt slot and to provide a C++ signature for it. PyQt5 provides the pyqtSlot() function decorator to do this.

...

Connecting a signal to a decorated Python method also has the advantage of reducing the amount of memory used and is slightly faster.

When is that decorating necessary?

The only case I know is when you want to call methods from a QML interface: you can pass an object derived from QObject to QML and call object's methods but only if these methods are decorated with @pyqtSlot decorator with defined signature.

For your case consider it as a good practice - denoting a method as a slot for some signal.