PyQt5 (five) signal and slot mechanism

The signal and slot mechanism is the core mechanism of QT. To be proficient in QT programming, you must have an understanding of signals and slots. Signals and slots are a high-level interface used for communication between objects. It is a core feature of QT and an important difference between QT and other toolkits.

Signals and slots are methods used to pass data between objects: when a specific event occurs, a signal is emitted, and slot calls are used to respond to the corresponding signal. Objects in Qt already contain many predefined signals (basic components have their own unique predefined signals), and new signals can be added according to the usage scenarios. Similarly, many predefined slot functions are already included in Qt objects, but new slot functions can also be added according to the usage scenarios.

1. Concept introduction

All controls that inherit qwidget support the signal and slot mechanism.

Signal: A message sent to the outside world when a signal changes.

When a signal is emitted, its associated slot function is executed immediately. The object is only responsible for sending the signal, and the object that emits the signal does not know which object is receiving the signal. This ensures low coupling between objects.
If there is a signal associated with multiple slot functions, when the signal is emitted, the execution order of these slots will be random and indeterminate.

Slot: A function or method that performs some action.

The slot is called when the signal connected to the slot is emitted. A slot does not know if any signals are connected to itself.

Signal and slot mechanism: mainly divided into two types

Manual operation: signal connection slot

Automatic operation: when the signal is emitted, successive slot functions are automatically executed

signal connection

By calling the QObject object's connect function to associate an object's signal with another object's slot function, when the sender emits a signal, the receiver's slot function will be called. The function is defined as follows:

object.信号.connet(槽函数)

The disconnect function can be used to disconnect a signal when it is not necessary to remain associated with a slot. It is defined as follows:

disconnect(槽函数)

Features of Signals and Slots:

1. A signal can be connected to multiple slots: when the signal is sent, the slot functions will be called, but the order of calling is random and uncertain.

2. Multiple signals can be connected to the same slot: any one of the signals is emitted, and the slot function will be executed.

3. The parameters of the signal can be any Python type, such as list, dict and other types unique to python. An example is given when customizing the signal.

4. The connection between signals and slots can be removed: such as disconnecting a specific signal.

5. A signal can be associated with another signal: after the first signal is sent, the second signal is sent at the same time. For example, after the signal to shut down the system is issued, the signal to save the data will be issued at the same time.

2. Code samples

The overall code is as follows:

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,QGridLayout,QLabel,QHBoxLayout, QGroupBox,
    QVBoxLayout, QApplication,QProgressBar,QPushButton,QMessageBox)


class SignalSlot(QWidget):

    def __init__(self):
        super(SignalSlot,self).__init__()      
        self.initUI()


    def initUI(self):

        self.controlsGroup = QGroupBox("运行样本")
        self.lcdNumber = QLCDNumber(self)
        self.slider = QSlider(Qt.Horizontal, self)
        self.pBar = QProgressBar(self)
        vbox = QVBoxLayout()
        vbox.addWidget(self.pBar)
        vbox.addWidget(self.lcdNumber)
        vbox.addWidget(self.slider)
        self.controlsGroup.setLayout(vbox)

        controlsLayout = QGridLayout()
        self.label1 = QLabel("保存状态:")
        self.saveLabel = QLabel()
        self.label2 = QLabel("运行状态:")
        self.runLabel = QLabel()
        self.buttonSave = QPushButton("保存")
        self.buttonRun = QPushButton("运行")
        self.buttonStop = QPushButton("停止")
        self.buttonDisconnect = QPushButton("解除关联")
        self.buttonConnect = QPushButton("绑定关联")

        controlsLayout.addWidget(self.label1,0,0)
        controlsLayout.addWidget(self.saveLabel,0,1)
        controlsLayout.addWidget(self.label2,1,0)
        controlsLayout.addWidget(self.runLabel,1,1)
        controlsLayout.addWidget(self.buttonSave,2,0)
        controlsLayout.addWidget(self.buttonRun,2,1)
        controlsLayout.addWidget(self.buttonStop,2,2)
        controlsLayout.addWidget(self.buttonDisconnect,3,0)
        controlsLayout.addWidget(self.buttonConnect,3,1)

        layout = QHBoxLayout()
        layout.addWidget(self.controlsGroup)
        layout.addLayout(controlsLayout)
        self.setLayout(layout)

        self.buttonRun.clicked.connect(self.buttonSave.clicked)
        self.slider.valueChanged.connect(self.pBar.setValue)
        self.slider.valueChanged.connect(self.lcdNumber.display)
        self.buttonSave.clicked.connect(self.showMessage)
        self.buttonRun.clicked.connect(self.showMessage)
        self.buttonDisconnect.clicked.connect(self.unbindConnection)
        self.buttonConnect.clicked.connect(self.bindConnection)
        self.buttonStop.clicked.connect(self.stop)

        self.setGeometry(300, 500, 500, 180)
        self.setWindowTitle('信号和槽')

    def showMessage(self):
        if self.sender().text() == "保存":
            self.saveLabel.setText("Saved")
        elif self.sender().text() == "运行":
            self.saveLabel.setText("Saved")
            self.runLabel.setText("Running")

    def unbindConnection(self):
        self.slider.valueChanged.disconnect()
    def bindConnection(self):
        self.slider.valueChanged.connect(self.pBar.setValue)
        self.slider.valueChanged.connect(self.lcdNumber.display)
    def stop(self):
        self.saveLabel.setText("")
        self.runLabel.setText("")

if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = SignalSlot()
    ex.show()
    sys.exit(app.exec_())

Control description:

control type control name effect
controlsGroup QGroupBox Provides support for building group boxes. A group box, usually with a border and a title bar, acts as a container widget in which various widgets can be arranged.
lcdNumber QLCDNumber Used to display a number with an LCD-like effect.
slider QSlider Provides a vertical or horizontal slider, a slider is a typical control for controlling bounded values, it allows the user to move the slider in a certain range in the horizontal or vertical direction, and the position of the slider is converted into a Integer value in legal range
pBar QProgressBar Provides a horizontal or vertical progress bar
label1 QLabel
  • Placeholder
  • display text
  • display image
  • place gif animation
  • Hyperlink
  • cue tag
buttonSave QPushButton Commonly used button controls

Interface description: 

The interface logic of program sample running, first set the number of running program samples, and then save the logic state of running after first. Change the display data of progressBar and LCD by sliding the slider; the “Save” button saves the running sample; the “Run” button runs the program sample; Will change the progressBar and LCD display.

self.controlsGroup = QGroupBox("运行样本")
self.lcdNumber = QLCDNumber(self)
self.slider = QSlider(Qt.Horizontal, self)
self.pBar = QProgressBar(self)
vbox = QVBoxLayout()
vbox.addWidget(self.pBar)
vbox.addWidget(self.lcdNumber)
vbox.addWidget(self.slider)
self.controlsGroup.setLayout(vbox)

Instantiate a QGroupBox and add QProgressBar, QLCDNumber, and QSlider controls to it.

controlsLayout = QGridLayout()
self.label1 = QLabel("保存状态:")
self.saveLabel = QLabel()
self.label2 = QLabel("运行状态:")
self.runLabel = QLabel()
self.buttonSave = QPushButton("保存")
self.buttonRun = QPushButton("运行")
self.buttonStop = QPushButton("停止")
self.buttonDisconnect = QPushButton("解除关联")
self.buttonConnect = QPushButton("绑定关联")

controlsLayout.addWidget(self.label1,0,0)
controlsLayout.addWidget(self.saveLabel,0,1)
controlsLayout.addWidget(self.label2,1,0)
controlsLayout.addWidget(self.runLabel,1,1)
controlsLayout.addWidget(self.buttonSave,2,0)
controlsLayout.addWidget(self.buttonRun,2,1)
controlsLayout.addWidget(self.buttonStop,2,2)
controlsLayout.addWidget(self.buttonDisconnect,3,0)
controlsLayout.addWidget(self.buttonConnect,3,1)

Add labels and buttons through QGridLayout().

layout = QHBoxLayout()
layout.addWidget(self.controlsGroup)
layout.addLayout(controlsLayout)
self.setLayout(layout)

 Finally, the left and right interfaces are merged through QHBoxLayout to form the final interface.

Signal and slot description:

Signal and slot are bound.
1. A signal binds multiple slots:

self.slider.valueChanged.connect(self.pBar.setValue)

self.slider.valueChanged.connect(self.lcdNumber.display)

The valueChanged signal of the slider control is also bound to the setValue() of QProgressBar and the display() slot function of QLCDNumber. When the valueChanged signal is triggered, these two slot functions will be called.

2. Multiple signals are bound to a slot:

self.buttonSave.clicked.connect(self.showMessage)
self.buttonRun.clicked.connect(self.showMessage)

The clicked signals of the two objects, buttonSave and buttonRun, are bound to the slot function showMessage(). No matter which signal is triggered, the slot function showMessage() will be called, and the different content displayed will be judged according to the function self.sender().text().

3. Signal and slot connections can be removed:

self.buttonDisconnect.clicked.connect(self.unbindConnection)

When the buttonDisconnect signal is triggered, the disconnect() method will be executed in the associated slot function unbindConnection(), as follows:

def unbindConnection(self):
        self.slider.valueChanged.disconnect()

When executing disconnect(), you can specify to disassociate with a specific slot, such as self.slider.valueChanged.disconnect(self.pBar.setValue), at this time disassociate with setValue() of QProgressBar, if not If specified, all slots associated with this signal will be released.

4. Correlation between signals and signals:

self.buttonRun.clicked.connect(self.buttonSave.clicked)

As mentioned in the sample description, the sample needs to be saved before running, so in order to ensure that the save operation is performed when running, the buttonRun.clicked signal is associated with the buttonSave.clicked signal.

In the example, when "Save" (buttonSave) is not executed, "Run" (buttonRun) is executed. At this time, since the clicked signals of the two objects are already associated, the clicked of buttonSave will also be executed.

Final Results:

This article is the fifth part of "Learn PyQt5 from Scratch" , I hope you can support and learn together!


refer to:

Pyqt5 series (seven) - signal and slot mechanism - The wind chasing the sun - CSDN blog - pyqt5 signal and slot

Guess you like

Origin blog.csdn.net/kobepaul123/article/details/122934359