Summary: in this tutorial, you’ll learn about PyQt signals & slots and how they work in PyQt applications.
Introduction to the PyQT signals and slots
Typically, a Python script runs from the top to the bottom as follows:
- Get inputs.
- Process the inputs to produce outputs.
- Write the outputs to the screen or a file.
This is called procedure programming.
When you create a GUI program, you use event-driven programming instead. In the event-driven programming paradigm, a program has the following flow:
- Create widgets like labels, line edits, and buttons.
- Start an event loop that waits for events.
- Respond to events when they occur by executing callables.
Note that a callable is a function, a method, or an object that implements the __call__()
method.
To connect events with callables of the program, PyQt uses the signals and slots mechanism.
Signals
A signal is a special property of an object that is emitted when an event occurs. An event may be a user action, a timeout, or the completion of an asynchronous operation.
Slots
A slot is a callable that can receive a signal and respond to it.
To respond to events, you connect signals to slots. When you connect a signal to a slot, the slot will be executed when the signal is emitted.
In PyQt, all subclasses of the QObject
class can send and receive signals. Almost all classes in PyQt are subclasses of the QObject
class.
Let’s take an example to understand how the PyQt signals & slots mechanism works.
PyQt signals & slots example
The following program displays a window that has a button. When you click the button, the program shows the clicked
message in the console:
import sys
from PyQt6.QtWidgets import (
QApplication,
QWidget,
QLineEdit,
QPushButton,
QVBoxLayout
)
class MainWindow(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# set the window title
self.setWindowTitle('Qt Signals & Slots')
# create a button widget and connect its clicked signal
# to a method
button = QPushButton('Click me')
button.clicked.connect(self.button_clicked)
# place the buton on window using a vertical box layout
layout = QVBoxLayout()
self.setLayout(layout)
layout.addWidget(button)
# show the window
self.show()
def button_clicked(self):
print('clicked')
if __name__ == '__main__':
app = QApplication(sys.argv)
# create the main window and display it
window = MainWindow()
# start the event loop
sys.exit(app.exec())
Code language: Python (python)
How it works. (We’ll focus on the signals & slots only)
First, create a push button using the QPushButton
widget:
button = QPushButton('Click me')
Code language: Python (python)
Second, connect the clicked
signal to the on_clicked
method (slot):
button.clicked.connect(self.button_clicked)
Code language: Python (python)
In general, the syntax for connecting a signal to a slot is as follows:
sender_object.signal_name.connect(receiver_object.slot_name)
Code language: Python (python)
Also, you can connect a signal to a slot when passing a slot to a signal as a keyword argument. For example:
button = QPushButton('Click me', clicked=self.button_clicked)
Code language: Python (python)
Third, define a method on_clicked
that prints the clicked message to the terminal:
def on_clicked(self):
print('clicked')
Code language: Python (python)
When you click the button, the QPushButton
emits the clicked signal that executes the connected slot on_clicked
.
Note that the following code places the button on the window using the vertical box layout. And you’ll learn more about it in the upcoming tutorial.
layout = QVBoxLayout()
self.setLayout(layout)
layout.addWidget(button)
Code language: Python (python)
Using signals that send data
A signal may carry data that provides the state of the object when the event occurs. For example, the textChanged
signal of the QLineEdit
has the text entered in the widget.
If a signal carries data, the connected slot can receive it.
The following program shows QLineEdit
and QLabel
widgets. When you type something on the QLineEdit
, the QLabel
will display it accordingly:
import sys
from PyQt6.QtWidgets import (
QApplication,
QWidget,
QLabel,
QLineEdit,
QVBoxLayout
)
class MainWindow(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setWindowTitle('Qt Signals & Slots')
# create widgets
label = QLabel()
line_edit = QLineEdit()
line_edit.textChanged.connect(label.setText)
# place the widgets
layout = QVBoxLayout()
layout.addWidget(label)
layout.addWidget(line_edit)
self.setLayout(layout)
# show the window
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec())
Code language: Python (python)
How it works.
First, create a QLabel
widget. The QLabel
widget has the setText()
method that sets its contents.
label = QLabel()
Code language: Python (python)
Second, create a new QLineEdit
widget:
line_edit = QLineEdit()
Code language: Python (python)
Third, connect the textChanged
signal to the setText
method of the QLabel
object:
line_edit.textChanged.connect(label.setText)
Code language: Python (python)
When you type something on the QLineEdit
:
- The
textChanged
signal sends the text - The
QLabel
receives the text and passes it to thesetText()
method.
Summary
- A signal is a special property of an object that is emitted when an event occurs.
- A slot is a callable that can receive a signal and respond to it accordingly.
- PyQt uses signals and slots to wire up events with callables.