Python qt: signals/slots
Sigals and Slots are Qt's way of communicating between widgets.
In order to run a GUI (or make use of nearly of any of Qt's classes) you must have a QCoreApplication (or subclass) running. This starts an eventloop, which enables communication between signals and slots.
Documentation
signals/slots implementation https://woboq.com/blog/how-qt-signals-slots-work.html
Signals
Basics
from Qt import QtWidgets def printhi(): print('hi') btn = QtWidgets.QPushButton('Press Me') btn.clicked.connect(printhi) # signal 'clicked' will call function 'printhi'Now whenever the button is clicked, the function
printhi
will be called. Consult the api to see a list of all of the signals an object has. You can also built custom signals.Repeating Signals
Signals can be connected to other signals. The connected signal gets emitted when it's source-signal gets called.
btnA = QtWidgets.QPushButton('press me') btnB = QtWidgets.QPushButton('or press me instead') btnA.clicked.connect(btnB.clicked)Custom Signals
class MyWorker(QtCore.QObject): started = QtCore.Signal() finished = QtCore.Signal() def start(self): self.started.emit() time.sleep(5) self.finished.emit() def printhi(): print('hi') worker = MyWorker() worker.finished.connect(printhi)In the above example, finished is emitted when the job is done. prinhi is called when it is signaled. You can only call signals on objects that are
QObject
subclasses.wrapping connections
Sometimes you want to connect a signal to a method that needs parameters that your signal does not pass. You can use python's
functools.partial
orlambda:
functions to wrap a signal's output. This is called currying.def print_message(message): print(message) btn.clicked.connect( functools.partial( print_message, 'hi' ) )
slots
Slots are simply functions that are allowed to be connected to Signals. PySide/PyQt are both very relaxed about this, allowing even lambda functions to be called. C++ is much more strict. See the Official C++ documentation for more details.
In python, you can define a slot using a decorator. So far this has not been necessary, but emulating C++ as closely as possible is likely a good practice in case future bindings abandon the flexible approach being used.
class MyWidget(QtWidgets.QWidget): @QtCore.Slot() def myslot(self): pass