Home » Tutorial: PyQt6 Signals and Slots

Tutorial: PyQt6 Signals and Slots

Java SE 11 Programmer II [1Z0-816] Practice Tests
1 Year Subscription
Spring Framework Basics Video Course
Java SE 11 Developer (Upgrade) [1Z0-817]
Oracle Java Certification
Java SE 11 Programmer I [1Z0-815] Practice Tests

PyQt6 is a powerful library for creating desktop GUI applications in Python.

A core concept in PyQt6 is signals and slots, which is a mechanism for communication between objects.

This allows one object to notify another about events or changes in state.

In this tutorial, we’ll cover:

1. Introduction to Signals and Slots

A signal is emitted when an event occurs, such as clicking a button. A slot is a method that is called in response to a signal.

Key Points

  • Signals are predefined or custom events.
  • Slots are any Python callable (function, method, etc.).
  • PyQt6 uses the @pyqtSlot decorator to define slots, though this is optional.

2. Connecting Signals to Slots

To connect a signal to a slot, use the .connect() method.

Example: Button Click Signal

import sys
from PyQt6.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Signals and Slots Example")

        # Create a button
        self.button = QPushButton("Click Me!")
        
        # Connect the button's clicked signal to a slot
        self.button.clicked.connect(self.on_button_clicked)

        # Set layout
        layout = QVBoxLayout()
        layout.addWidget(self.button)
        self.setLayout(layout)

    def on_button_clicked(self):
        print("Button was clicked!")

# Application setup
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())

When the button is clicked, the on_button_clicked slot is triggered, printing a message to the console.

3. Creating Custom Signals

Custom signals allow you to define specific events. Use the pyqtSignal class from PyQt6.QtCore.

Example: Custom Signal

from PyQt6.QtCore import pyqtSignal, QObject

class Communicator(QObject):
    # Define a custom signal
    custom_signal = pyqtSignal(str)

class Receiver:
    def slot_function(self, message):
        print(f"Received message: {message}")

# Usage
sender = Communicator()
receiver = Receiver()

# Connect the custom signal to the receiver's slot function
sender.custom_signal.connect(receiver.slot_function)

# Emit the signal
sender.custom_signal.emit("Hello, PyQt6!")

In this example:

  • custom_signal is a signal that carries a str argument.
  • slot_function is the slot that receives and processes the signal.

4. Disconnecting Signals

You can disconnect a signal from a slot using the .disconnect() method.

Example: Disconnecting Signals

class Test(QObject):
    signal = pyqtSignal()

def example_function():
    print("Signal received.")

# Create objects
test = Test()

# Connect and disconnect
test.signal.connect(example_function)
test.signal.disconnect(example_function)

# Emit the signal (this will do nothing as it's disconnected)
test.signal.emit()

5. Practical Examples

Example 1: Passing Data with Signals

from PyQt6.QtWidgets import QLabel, QLineEdit, QVBoxLayout, QWidget, QApplication
from PyQt6.QtCore import pyqtSignal

class DataEmitter(QWidget):
    data_signal = pyqtSignal(str)  # Signal carrying string data

    def __init__(self):
        super().__init__()
        self.setWindowTitle("Passing Data with Signals")

        # Widgets
        self.input = QLineEdit(self)
        self.label = QLabel("Type something:", self)

        # Layout
        layout = QVBoxLayout()
        layout.addWidget(self.input)
        layout.addWidget(self.label)
        self.setLayout(layout)

        # Connect input's textChanged signal to the custom signal
        self.input.textChanged.connect(self.emit_data)

        # Connect custom signal to the label's slot
        self.data_signal.connect(self.update_label)

    def emit_data(self, text):
        self.data_signal.emit(text)

    def update_label(self, text):
        self.label.setText(f"You typed: {text}")

# Application setup
app = QApplication([])
window = DataEmitter()
window.show()
app.exec()

In this example:

  • The textChanged signal of the QLineEdit widget is connected to the emit_data method.
  • The custom signal data_signal is connected to the update_label method.

Example 2: Multi-Connection Signals

A signal can be connected to multiple slots.

class MultiSlotExample(QObject):
    signal = pyqtSignal()

def slot_one():
    print("Slot One Triggered")

def slot_two():
    print("Slot Two Triggered")

example = MultiSlotExample()
example.signal.connect(slot_one)
example.signal.connect(slot_two)

example.signal.emit()

Output:

Slot One Triggered
Slot Two Triggered

Example 3: Using Decorators for Slots

from PyQt6.QtCore import pyqtSignal, pyqtSlot, QObject

class DecoratorExample(QObject):
    signal = pyqtSignal(int)

    @pyqtSlot(int)
    def slot_function(self, value):
        print(f"Received value: {value}")

example = DecoratorExample()
example.signal.connect(example.slot_function)
example.signal.emit(42)

Using the @pyqtSlot decorator optimizes signal-slot connections but is optional.

Summary

  • Signals and slots enable flexible and decoupled event handling.
  • Predefined signals (e.g., clicked) are easy to use.
  • Custom signals add versatility to PyQt6 applications.
  • Multiple slots can be connected to a single signal, and vice versa.

You may also like

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More