Introduction to Signals and Slots
Signal (Signal) and Slot (Slot) is the core mechanism in Qt, but also in the PyQt programming between the object communication mechanism.PyQt's window control class has a lot of built-in signals, developers can also add custom signals. Signals and slots have the following characteristics:
- One signal can be connected to multiple slots.
- One signal can be connected to another.
- The signal argument can make any Python type.
- One slot can be connected to multiple signals.
- Signals can be connected to slots either synchronously or asynchronously.
- Signal to slot connections may cross threads.
- The signal can be disconnected.
Use of built-in signals and slots
The use of the built-in clicked signal connection slot function is demonstrated here
import sys from import QPushButton, QApplication, QWidget, QMessageBox app = QApplication() widget = QWidget() def showMsg(): (widget, "Information Alert Box", "Ok, pop-up test message.") btn = QPushButton("Test Click Button", widget) (showMsg) () (app.exec_())
Use of custom signals and slots
import sys from import QObject, pyqtSignal # Signal Objects class QTypeSignal(QObject): # Define a signal sendmsg = pyqtSignal(object) def __init__(self): super(QTypeSignal, self).__init__() def run(self): # Transmit signals ('Hello PyQt5') # Slot objects class QTypeSlot(QObject): def __init__(self): super(QTypeSlot, self).__init__() # Slot functions in slot objects def get(self, msg): print("QSlot get msg => " + msg) if __name__ == "__main__": send = QTypeSignal() slot = QTypeSlot() # 1 print("--- Bind signals to slot functions ---") () () # 2 print('--- Disconnect the signal from the slot function ---') () ()
Custom signals and built-in slot functions
import sys from import * from import * from import Qt class WinForm (QWidget): # Custom signals without parameters button_clicked_signal = pyqtSignal() def __init__(self, parent=None): super(WinForm, self).__init__(parent) ("Examples of custom signals and built-in slot functions") (330, 50) btn = QPushButton("Close.", self) # Connecting signals to slot functions (self.btn_clicked) # Receive signal, connect to slot function self.button_clicked_signal.connect() def btn_clicked(self): # Send customized signal, no parameters self.button_clicked_signal.emit() if __name__ == "__main__": app = QApplication() win = WinForm() () (app.exec_())
Custom signals and custom slot functions
import sys from import * from import * class WinForm(QWidget): # Custom signals, no parameters button_clicked_signal = pyqtSignal() def __init__(self, parent= None): super(WinForm, self).__init__(parent) ("Customized Signal and Slot Function Examples") (350, 50) btn = QPushButton("Close.", self) (self.btn_clicked) self.button_clicked_signal.connect(self.btn_close) def btn_clicked(self): self.button_clicked_signal.emit() def btn_close(self): () if __name__ == "__main__": app = QApplication() win = WinForm() () (app.exec_())
Custom parametric signals
import sys from import pyqtSignal, QObject class CustSignal(QObject): # Declare signals without parameters signal1 = pyqtSignal() # Declare a signal with a parameter of type int signal2 = pyqtSignal(int) # Declare signals with one int and one str type parameter signal3 = pyqtSignal(int, str) # Declare a signal with a list type parameter signal4 = pyqtSignal(list) # Declare a signal with a dictionary type parameter signal5 = pyqtSignal(dict) # Declare a multi-overloaded version of the signal, including signals with int and str type parameters and signals with str type parameters signal6 = pyqtSignal([int,str], [str]) def __init__(self, parent=None): super(CustSignal, self).__init__(parent) # Connect the signal to the specified slot function self.(self.signalCall1) self.(self.signalCall2) self.(self.signalCall4) self.(self.signalCall4) self.(self.signalCall5) self.signal6[int, str].connect(self.signalCall6) self.signal6[str].connect(self.signalCall6OverLoad) # Transmit signals self.() self.(100) self.(200, 'hello') self.([1,2,3,4,5,6]) self.({"name":"xiaowang", "age":"25"}) self.signal6[int, str].emit(300, 'hello world') self.signal6[str].emit('hello pyqt') def signalCall1(self): print('signal1 emit') def signalCall2(self, val): print('signal3 emit, value:', val) def signalCall3(self, val, text): print('signal3 emit, value:', val, text) def signalCall4(self, val): print('signal4 emit, value:', val) def signalCall5(self, val): print('signal5 emit, value:', val) def signalCall6(self, val, text): print('signal6 emit, value:', val, text) def signalCall6OverLoad(self, val): print('signal6 overload emit, value:', val) if __name__ == "__main__": custSignal = CustSignal()
Using Custom Signal Parameters
For the clicked signal he is no parameters, if connected to the slot function hopefully can receive parameters, if directly connected to the slot function with parameters will be an error, because the number of parameters issued by the signal must be greater than the number of parameters received by the slot function. Here are two solutions:
1. Use lambda
2. Use the partial function in the functools module.
import sys from import * from import * from functools import partial, partialmethod class WinForm(QMainWindow): def __init__(self, parent=None): super(WinForm, self).__init__(parent) ("Solution for a parametric slot function to receive an unparameterized signal.") button1 = QPushButton("Button 1") button2 = QPushButton("Button 2") # For the clicked signal he has no parameters, if the connected slot function wants to receive parameters, if the direct connection has parameters #'s slot function will error out because the number of arguments signaled must be greater than the number of arguments received by the slot function. There are two solutions here: # 1. Using lambda # 2. Using the partial function in the functools module # Use lambda (lambda: (1)) # Use the partial function in the functools module (partial(, 2)) layout = QHBoxLayout() (button1) (button2) mainwidget = QWidget() (layout) (mainwidget) def onButtonClick(self, n): print("Button {0} It's pressed.".format(n)) (self, "Information Alert Box", 'Button {0} clicked'.format(n)) if __name__ == "__main__": app = QApplication() win = WinForm() () (app.exec_())
Decorator signals and slots
@(parameter)
def on_sender_object_name_transmit_signal_name (self, arguments):
pass
This line of code must have been executed first: (self)
from PyQt5 import QtCore from import QApplication, QWidget, QHBoxLayout, QPushButton, QMessageBox import sys # Decorator signals and slots # @(parameter) # def on_sender_object_name_transmit_signal_name (self, arguments): # pass # # This line of code must be executed first: (self) class CustWidget(QWidget): def __init__(self, parent=None): super(CustWidget, self).__init__(parent) ("Decorator Signal and Slot Demo.") (350, 50) = QPushButton("OK", self) # Set the object name using setObjectName ("okButton") layout = QHBoxLayout() () (layout) (self) @() def on_okButton_clicked(self): print("The OK button was clicked.") (self, "Information Alert Box", "The OK button was clicked.") if __name__ == "__main__": app = QApplication() win = CustWidget() () (app.exec_())
Disconnecting and connecting signals to slots
import sys from import * from import * # Signal disconnected from slot class SignalClass(QObject): # Declare signals without parameters signal1 = pyqtSignal() # Declare a signal with a parameter of type int signal2 = pyqtSignal(int) def __init__(self, parent=None): super(SignalClass, self).__init__(parent) # Connect the signal signal1 to the two slot functions sig1Call and sig2Call self.(self.sig1Call) self.(self.sig2Call) # Connect signal2 to signal1 self.(self.signal1) # Transmit signals self.() self.(1) # Disconnect signal1,signal2 signals from each slot function self.(self.sig1Call) self.(self.sig2Call) self.(self.signal1) # Connect signals signal1 and signal2 to the same slot function sig1Call self.(self.sig1Call) self.(self.sig1Call) # Re-transmit the signal self.() self.(2) def sig1Call(self): print('signal-1 emit') def sig2Call(self): print('signal-2 emit') if __name__ == "__main__": signal = SignalClass()
The use of signals and slots in multithreading
import sys from import QApplication, QWidget from import QThread, pyqtSignal class Main(QWidget): def __init__(self, parent=None): super(Main, self).__init__(parent) # Create a thread instance and set the name, variables, signals and slots = MyThread() ("thread1") () (6) def outText(self, text): print(text) class MyThread(QThread): sinOut = pyqtSignal(str) def __init__(self, parent=None): super(MyThread, self).__init__(parent) = None def setIdentity(self, text): = text def setVal(self, val): = int(val) # Execute the thread run method () def run(self): while > 0 and : # Transmit signals ( + "==>" + str()) -= 1 if __name__ == '__main__': app = QApplication() main = Main() () (app.exec_())
The above is a detailed explanation of PyQt5 signal (Signal) and slot (Slot) of the details, more about PyQt5 signal Slot information please pay attention to my other related articles!