当前位置:网站首页>Pyside6 signal, slot

Pyside6 signal, slot

2022-07-06 16:00:00 Catch the king before the thief

Introduction to signal and slot applications ( One ):https://blog.csdn.net/jia666666/article/details/81774175
Subdivision of signal and slot ( Two ):https://blog.csdn.net/jia666666/article/details/81774858
Advanced play of signals and slots ( 3、 ... and ):https://blog.csdn.net/jia666666/article/details/81775378
Advanced usage of signals and slots ( Four ):https://blog.csdn.net/jia666666/article/details/81775614
Qt Designer God assists ( 5、 ... and ):https://blog.csdn.net/jia666666/article/details/81780619
Use of signals and slots in multithreading ( 6、 ... and ):https://blog.csdn.net/jia666666/article/details/81780930
Multi window data transmission ( 7、 ... and ):https://blog.csdn.net/jia666666/article/details/81781697
Event handling mechanism ( 8、 ... and ):https://blog.csdn.net/jia666666/article/details/81781992

1、 according to Use To classify

1. Built in signal 、 built-in Slot

Use of built-in signal and slot , When transmitting a signal , Functions using window controls , Not a custom function , This is also the one we used most in the past . Example :

# -*- coding: utf-8 -*-

import sys
from PySide6.QtWidgets import QMessageBox, QPushButton, QApplication, QWidget


def show_msg():
    QMessageBox.information(widget, ' Message box ', 'Ok  Pop up test information ')


app = QApplication(sys.argv)
widget = QWidget()
btn = QPushButton(' Test click the button ', widget)
btn.clicked.connect(show_msg)
widget.resize(300, 300)
widget.show()
sys.exit(app.exec())

This example will build a button object clicked Signals and custom slot functions show_msg() Connect . Click the button , This slot function will be triggered , Pop up a message box

2. Custom signal 、 Custom slot

Customize the use of signals and slots : When transmitting a signal , Functions that do not use window controls , Instead, use custom functions ,( Simply put, use oyqtsSignal Class instances emit signals ), The reason for using custom signals and slots , Because transmitting signals through built-in functions has its own defects , First , Built in functions only contain some commonly used signals , Some signal transmissions cannot find the corresponding built-in function , Secondly, under certain circumstances , To transmit this signal , Such as the click event of the button , Last , The parameters passed by the built-in function are specific , You can't customize , Using custom signal and slot functions does not have these defects

stay pyqt5 in , The application of customized signals and slots is very flexible , For example, because of business needs , In some places in the program, you need to send a signal , Transfer a variety of data , Then accept the data in the slot function , In this way, you can flexibly implement some business logic

A simple example : Simple custom signal and slot

import sys
from PySide6 import QtCore


#  Define a name as  say_some_words  Of  slot,  And receive string
@QtCore.Slot(str)
def say_some_words(words):
    print(words)


#  Signal object 
class Communicate(QtCore.QObject):
    #  Create a name called  speak  The signal of 
    speak = QtCore.Signal(str)


some_one = Communicate()
# connect signal and slot
some_one.speak.connect(say_some_words)
# emit 'speak' signal
some_one.speak.emit("Hello everybody!")

Add overloads :

import sys
from PySide6 import QtCore


# define a new slot that receives a C 'int' or a 'str'
# and has 'saySomething' as its name
@QtCore.Slot(int)
@QtCore.Slot(str)
def say_something(stuff):
    print(stuff)


class Communicate(QtCore.QObject):
    # create two new signals on the fly: one will handle
    # int type, the other will handle strings
    speakNumber = QtCore.Signal(int)
    speakWord = QtCore.Signal(str)


someone = Communicate()
# connect signal and slot properly
someone.speakNumber.connect(say_something)
someone.speakWord.connect(say_something)
# emit each 'speak' signal
someone.speakNumber.emit(10)
someone.speakWord.emit("Hello everybody!")

Use slot overload and some complex signal connection and transmission

import sys
from PySide6 import QtCore


# define a new slot that receives an C 'int' or a 'str'
# and has 'saySomething' as its name
@QtCore.Slot(int)
@QtCore.Slot(str)
def say_something(stuff):
    print(stuff)


class Communicate(QtCore.QObject):
    # create two new signals on the fly: one will handle
    # int type, the other will handle strings
    speak = QtCore.Signal((int,), (str,))


someone = Communicate()
# connect signal and slot. As 'int' is the default
# we have to specify the str when connecting the
# second signal
someone.speak.connect(say_something)
someone.speak[str].connect(say_something)

# emit 'speak' signal with different arguments.
# we have to specify the str as int is the default
someone.speak.emit(10)
someone.speak[str].emit("Hello everybody!")

Example :

import sys
from PySide6.QtCore import QObject, Signal, Slot

"""
PyQt Another way is used . In order to PyQt Scripts switch to PySide function 
 Just use the following code to modify .
from PySide.QtCore import Signal as pyqtSignal
from PySide.QtCore import Slot as pyqtSlot
 perhaps 
QtCore.pyqtSignal = QtCore.Signal
QtCore.pyqtSlot = QtCore.Slot
"""


#  Signal object 
class CustomSignal(QObject):
    #  Define a signal 
    signal_send_msg = Signal(str, str)

    def __init__(self):
        super(CustomSignal, self).__init__()

    def run(self):
        #  Send a signal 
        # self.sendmsg.emit('hell')

        #  Launch multiple parameters 
        self.signal_send_msg.emit(' The first parameter ', ' The second parameter ')


#  Slot object 
class CustomSlot(QObject):
    def __init__(self):
        super(CustomSlot, self).__init__()
        self.temp = None

    #  Slot function in slot object 
    # def get( self,msg ):
    #     print("QSlot get msg => " + msg)

    #  Multiple parameters 
    def get_msg(self, msg1, msg2):
        self.temp = None
        print("QSlot get msg => " + msg1 + ' ' + msg2)


if __name__ == '__main__':

    custom_signal = CustomSignal()  #  Instantiate the signal object 
    custom_slot = CustomSlot()    #  Instantiate the slot object 

    #  Bind the signal to the slot function 
    custom_signal.signal_send_msg.connect(custom_slot.get_msg)
    custom_signal.run()

    #  Unbind the signal from the slot function 
    custom_signal.signal_send_msg.disconnect(custom_slot.get_msg)
    custom_signal.run()

3. The signal of the decorator 、 Slot

The so-called decorator signal and slot , It is through Decorator To define signals and slot functions

Example : adopt  @QtCore.Slot(str) Decorate a function , Turn the function into a Slot function

import sys
from PySide6 import QtCore


#  Define a name as  say_some_words  Of  slot,  And receive string
@QtCore.Slot(str)
def say_some_words(words):
    print(words)


#  Signal object 
class Communicate(QtCore.QObject):
    #  Create a name called  speak  The signal of 
    speak = QtCore.Signal(str)


some_one = Communicate()
# connect signal and slot
some_one.speak.connect(say_some_words)
# emit 'speak' signal
some_one.speak.emit("Hello everybody!")

2、 According to the properties of signal and slot

Built in signal 、 Built in slot function

Demo close window when clicked , Use built-in signal and slot functions

# -*- coding: utf-8 -*-

from PySide6.QtWidgets import *
import sys


class WinForm(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle(' Built in signal / Slot example ')
        self.resize(300, 150)
        btn = QPushButton(' close ', self)
        btn.clicked.connect(self.close)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = WinForm()
    win.show()
    sys.exit(app.exec())

Built in signal 、 Custom slot function

# -*- coding: utf-8 -*-

from PySide6.QtWidgets import *
import sys


class WinForm(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle(' Examples of built-in signals and custom slot functions ')
        self.resize(300, 150)
        btn = QPushButton(' close ', self)
        btn.clicked.connect(self.btn_close)

    def btn_close(self):
        #  Custom slot function 
        self.close()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = WinForm()
    win.show()
    sys.exit(app.exec())

Custom signal 、 Built in slot function

# -*- coding: utf-8 -*-

import sys
from PySide6 import QtCore
from PySide6.QtWidgets import *


class WinForm(QWidget):
    #  Custom signal , With no arguments 
    button_clicked_signal = QtCore.Signal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle(' Examples of custom signals and built-in slot functions ')
        self.resize(300, 150)
        btn = QPushButton(' close ', self)
        #  Connect   Signals and slots 
        btn.clicked.connect(self.btn_clicked)
        #  Received signal , Connect to slot 
        self.button_clicked_signal.connect(self.close)

    def btn_clicked(self):
        #  Send custom signal , No parameter 
        self.button_clicked_signal.emit()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = WinForm()
    win.show()
    sys.exit(app.exec())

Custom signal 、 Custom slot function

# -*- coding: utf-8 -*-

import sys
from PySide6 import QtCore
from PySide6.QtWidgets import *


class WinForm(QWidget):
    #  Custom signal , With no arguments 
    button_clicked_signal = QtCore.Signal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle(' Examples of custom signals and slot functions ')
        self.resize(300, 150)
        btn = QPushButton(' close ', self)
        #  Connect   Signals and slots 
        btn.clicked.connect(self.btn_clicked)
        #  Received signal , Connect to the custom slot function 
        self.button_clicked_signal.connect(self.btn_close)

    def btn_clicked(self):
        #  Send custom signal , No parameter 
        self.button_clicked_signal.emit()

    def btn_close(self):
        self.close()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = WinForm()
    win.show()
    sys.exit(app.exec())

3、 The signal 、 Slot Advanced usage

Advanced , When customizing signals and slots , Parameters can be passed .

Custom signal general process

Defining signals

Define the slot function

Connect the signal to the slot function

Send a signal

Definition The signal

adopt Class member variable Define signal object

signal1 = QtCore.Signal()          #  Parameterless signal 
signal2 = QtCore.Signal(int)       #  With one parameter ( Integers ) The signal of 
signal3 = QtCore.Signal(int, str)  #  With two parameters ( Integers , character string ) The signal of 
signal4 = QtCore.Signal(list)      #  With one parameter ( list ) The signal of 
signal5 = QtCore.Signal(dict)      #  With one parameter ( Dictionaries ) The signal of 
signal6 = QtCore.Signal([int, str], [str])  #  belt ( Integers   character string ) perhaps ( character string ) The signal of 

Definition Slot function

Define a slot function , It has several different input parameters

def signal_call_1(self):
    print("signal1 emit")

def signal_call_2(self, val):
    print('signal2 emit,value:', val)

def signal_call_3(self, val, text):
    print('signall3 emit,value:', val, text)

def signal_call_4(self, val):
    print('signal4 emit,value:', val)

def signal_call_5(self, val):
    print('signal5 emit,value', val)

def signal_call_6(self, val, text):
    print('signal6 emit,value', val, text)

def signal_call_7(self, val):
    print('signal6 overload emit', val)

Connecting signals And Slot function

# Link between signal and slot function 
self.signal1.connect(self.signal_call_1)
self.signal2.connect(self.signal_call_2)
self.signal3.connect(self.signal_call_3)
self.signal4.connect(self.signal_call_4)
self.signal5.connect(self.signal_call_5)
self.signal6[int,str].connect(self.signal_call_6)
self.signal6[str].connect(self.signal_call_7)

Send a signal

# Signal transmission 
self.signal1.emit()
self.signal2.emit(1)
self.signal3.emit(1,' Third ')
self.signal4.emit([1,2,3,4])
self.signal5.emit({"name":'JIA','age':'21'})
self.signal6[int,str].emit(1," The sixth ")
self.signal6[str].emit(' The sixth ')

example : The complete code is as follows

# -*- coding: utf-8 -*-

import sys
from PySide6.QtWidgets import *
from PySide6.QtCore import QObject, Signal, Slot


class CustomSignal(QObject):

    signal1 = Signal()     #  Parameterless signal 
    signal2 = Signal(int)  #  With one parameter ( Integers ) The signal of 
    signal3 = Signal(int, str)  #  With two parameters ( Integers , character string ) The signal of 
    signal4 = Signal(list)  #  With one parameter ( list ) The signal of 
    signal5 = Signal(dict)  #  With one parameter ( Dictionaries ) The signal of 
    signal6 = Signal([int, str], [str])  #  belt ( Integers   character string ) perhaps ( character string ) The signal of 

    def __init__(self, parent=None):
        super(CustomSignal, self).__init__(parent)

        #  Link between signal and slot function 
        self.signal1.connect(self.signal_call_1)
        self.signal2.connect(self.signal_call_2)
        self.signal3.connect(self.signal_call_3)
        self.signal4.connect(self.signal_call_4)
        self.signal5.connect(self.signal_call_5)
        self.signal6[int, str].connect(self.signal_call_6)
        self.signal6[str].connect(self.signal_call_7)

        #  Signal transmission 
        self.signal1.emit()
        self.signal2.emit(1)
        self.signal3.emit(1, ' Third ')
        self.signal4.emit([1, 2, 3, 4])
        self.signal5.emit({"name": 'JIA', 'age': '21'})
        self.signal6[int, str].emit(1, " The sixth ")
        self.signal6[str].emit(' The sixth ')

    #  Slot function 
    def signal_call_1(self):
        print("signal1 emit")

    def signal_call_2(self, val):
        print('signal2 emit,value:', val)

    def signal_call_3(self, val, text):
        print('signall3 emit,value:', val, text)

    def signal_call_4(self, val):
        print('signal4 emit,value:', val)

    def signal_call_5(self, val):
        print('signal5 emit,value', val)

    def signal_call_6(self, val, text):
        print('signal6 emit,value', val, text)

    def signal_call_7(self, val):
        print('signal6 overload emit', val)


if __name__ == '__main__':
    custom_signal = CustomSignal()

Transfer of custom parameters

During programming , We often encounter the situation of passing custom parameters to slot functions , For example, the connection between a signal and a slot function is

button.clicked.connect(show_page)

about clicked The signal , It has no parameters , about show_page In terms of functions , I hope he can accept the parameters , hope show_page The function is as follows

def show_page(self,name):
    print(name', Click. ’)

Then there will be a problem , The number of parameters sent by the signal is different from the number of parameters accepted by the slot function , So how to solve this problem ? Here are two solutions ;

  • The first one is :lamdba expression
  • The second kind : Use functools Medium partial function

The two methods , It is written below , You can run it yourself , Pay attention to the notes .

# -*- coding: utf-8 -*-

import sys
from PySide6.QtWidgets import *
from PySide6.QtCore import QObject, Signal, Slot
from functools import partial


class WinForm(QMainWindow):
    def __init__(self, parent=None):
        super(WinForm, self).__init__(parent)
        #  Instantiate two buttons 
        button1 = QPushButton('Button1')
        button2 = QPushButton('Button2')

        # todo  The first method 
        #  Click signal correlation slot function , utilize  lambda  The expression passes a parameter 
        # button1.clicked.connect(lambda :self.onButtonClick(1))
        # button2.clicked.connect(lambda :self.onButtonClick(2))
        #
        # todo  The second method 
        button1.clicked.connect(partial(self.btn_click, 1))
        button2.clicked.connect(partial(self.btn_click, 2))

        #  Instantiation window 
        main = QWidget()
        #  Set the layout of the window , And add controls to it 
        layout = QHBoxLayout(main)
        layout.addWidget(button1)
        layout.addWidget(button2)
        #  Set as central control 
        self.setCentralWidget(main)
        self.resize(500, 500)

    def btn_click(self, n):
        #  Pop up information prompt box , Output the clicked information 
        print("Button {0}".format(n))
        QMessageBox.information(self, ' Message box ', 'Button {0}'.format(n))


if __name__ == '__main__':
    app = QApplication(sys.argv)
    form = WinForm()
    form.show()
    sys.exit(app.exec_())

Use lambda The expression passes the button number to the slot function , Of course, it can also pass on other things , Even the button itself

button1.clicked.connect(lambda :self.onButtonClick(1))
button2.clicked.connect(lambda :self.onButtonClick(2))

Use functools Medium partial Functions can fix function parameters

button1.clicked.connect(partial(self.onButtonClick, 1))
button2.clicked.connect(partial(self.onButtonClick, 2))

Decorator signal and slot

The so-called decorator signal and slot , It is to define signals and slot functions through decorators .

as follows

@PySide6.QtCore.Slot( Parameters )
def on_ Sender object name ) Transmit signal name (self, Parameters ):
    pass

The premise of this method is that the following functions have been executed :

QMetaObject.connectSlotsByName(QObject)

In the code above ," Sender object name "  Is the use of "setObjectName function " Name of the setting . Therefore, the naming rules of user-defined slot functions can also be seen as :

on + Use setObjectName Name of the setting + Signal name

Specific examples

# -*- coding: utf-8 -*-

import sys
from PySide6.QtWidgets import *
from PySide6.QtCore import QObject, Signal, Slot, QMetaObject


class WinForm(QWidget):
    def __init__(self, parent=None):
        super(WinForm, self).__init__(parent)

        self.btn_ok = QPushButton('ok', self)  #  Create button , Add to your own window 
        self.btn_ok.setObjectName('btn_ok')  #  Use  setObjectName  Set object name 

        #  Set its layout as horizontal , And add a button control to it 
        layout = QHBoxLayout(self)
        layout.addWidget(self.btn_ok)
        self.resize(300, 150)

        # TODo  The first method 
        # self.okButton.clicked.connect(self.btn_ok_clicked)

        #  The second method 
        QMetaObject.connectSlotsByName(self)

    # def btn_ok_clicked(self):
    #     print(' Click ok Button ')

    @Slot()
    def on_btn_ok_clicked(self):
        print(' Click ok Button ')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    form = WinForm()
    form.show()
    sys.exit(app.exec())

QtCore.QMetaObject.connectSlotsByName(self)  yes PySide6  According to the The signal name is automatically connected to the core code of the slot function , This line of code is used to put QObject Some objects of the descendant objects in are in accordance with their objectName Connect to the corresponding slot function .

For example, name , Suppose the code QtCore.QMetaObject.connectSlotsByName(self) Has been performed , Then the following code

@QtCore.Slot()
def on_okButton_clicked(self):
    print(' Click ok Button ')

It will be automatically recognized as the following code

def __init__(self,parent=None):
    self.okButton.clicked.connect(self.okButton_clicked)

def okButton_clicked(self):
        print(' Click ok Button ')

Disconnection and connection of signal and slot

Sometimes for some reason , Want to temporarily or permanently disconnect a signal from the slot function , Generally put connect prefix dis It means unbinding : namely disconnect

Examples are as follows

# -*- coding: utf-8 -*-

import sys
from PySide6.QtWidgets import *
from PySide6.QtCore import QObject, Signal, Slot, QMetaObject


class SignalClass(QObject):

    signal1 = Signal()     #  Declare a signal without parameters 
    signal2 = Signal(int)  #  The declaration takes a int Signal of type parameter 

    def __init__(self, parent=None):
        super(SignalClass, self).__init__(parent)
        #  take  signal1  The signal is connected to two slot functions 
        self.signal1.connect(self.sig1Call)
        self.signal1.connect(self.sig2Call)

        #  take signal2 The signal is connected to the signal 1
        self.signal2.connect(self.signal1)

        #  Send a signal 
        self.signal1.emit()
        self.signal2.emit(1)

        #  Disconnect the relationship between the signal and the slot function 
        self.signal1.disconnect(self.sig1Call)
        self.signal1.disconnect(self.sig2Call)
        self.signal2.disconnect(self.signal1)

        #  Bind signal and slot function 
        self.signal1.connect(self.sig1Call)
        self.signal2.connect(self.sig1Call)

        #  Signal transmission 
        self.signal1.emit()
        self.signal2.emit(1)

    #  The output signal 1 launch 
    def sig1Call(self):
        print('signal-1 emit')

    #  The output signal 2 launch 
    def sig2Call(self):
        print('signal-2 emit')


if __name__ == '__main__':
    signal = SignalClass()

4、 The signal And Slot And Qt Designer God assists

The front is the signal of manual input code and the use method of slot , Because it will be simpler to introduce in this way . But in practical application , because Qt Designer It can well realize the separation of interface display and business logic , If it can be used Qt Designer Automatically create some signals and slot mechanisms , So much the better

The function of this example is : The use of signals is explained in detail through an analog printing interface , When printing , You can set the number of copies to print , Paper type , After triggering the print button , Display the execution results on the right , adopt QCheckBox( Full screen preview Check box ) To choose whether to preview in full screen mode , Display the execution results on the right
Press F1 Key can display helpmessage Help information

First step :Qt Designer

First , Use Qt Designer Create a new template named widget Simple window , By way of widget box Drag the control of the area into the window , Realize the interface effect as shown in the figure

Here is a brief description of the window control

Control types Control name effect
QSpinBoxnumberSpinBox Show printed scores
QComboBoxstyleCombo Displays the type of paper printed , Paper types include A3,A4 etc.
QPushButtonprintButton Connect emitPrintSiagnal Function binding , Trigger custom signals printSignal The launch of
QCheckBoxprievewState Whether to preview in full screen
QPushButtonpriviewButton Connect emitPreviewSignal Function binding , Trigger custom signals previewSignal The launch of
QLabelresultLabel Show execution results

The second step : Add the interface file ui Convert to py file

pyuic5 -o xxxxx.py xxxxx.ui

It will generate a py file , In order to separate the display of the window from the business logic , Creating a file displayed in the call window , Add multiple custom signals to the calling class , And bind with slot function , The complete code is as follows

# -*- coding: utf-8 -*-

import sys
from PySide6 import QtCore, QtGui, QtWidgets
from PySide6.QtWidgets import *


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("Form")
        MainWindow.resize(715, 225)
        self.controlsGroup = QtWidgets.QGroupBox(MainWindow)
        self.controlsGroup.setGeometry(QtCore.QRect(10, 20, 451, 151))
        self.controlsGroup.setObjectName("controlsGroup")
        self.widget = QtWidgets.QWidget(self.controlsGroup)
        self.widget.setGeometry(QtCore.QRect(10, 40, 411, 30))
        self.widget.setObjectName("widget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.label = QtWidgets.QLabel(self.widget)
        self.label.setObjectName("label")
        self.horizontalLayout.addWidget(self.label)
        self.numberSpinBox = QtWidgets.QSpinBox(self.widget)
        self.numberSpinBox.setObjectName("numberSpinBox")
        self.horizontalLayout.addWidget(self.numberSpinBox)
        self.styleCombo = QtWidgets.QComboBox(self.widget)
        self.styleCombo.setObjectName("styleCombo")
        self.styleCombo.addItem("")
        self.styleCombo.addItem("")
        self.styleCombo.addItem("")
        self.horizontalLayout.addWidget(self.styleCombo)
        self.label_2 = QtWidgets.QLabel(self.widget)
        self.label_2.setObjectName("label_2")
        self.horizontalLayout.addWidget(self.label_2)
        self.printButton = QtWidgets.QPushButton(self.widget)
        self.printButton.setObjectName("printButton")
        self.horizontalLayout.addWidget(self.printButton)
        self.widget1 = QtWidgets.QWidget(self.controlsGroup)
        self.widget1.setGeometry(QtCore.QRect(10, 100, 201, 30))
        self.widget1.setObjectName("widget1")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget1)
        self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.previewStatus = QtWidgets.QCheckBox(self.widget1)
        self.previewStatus.setObjectName("previewStatus")
        self.horizontalLayout_2.addWidget(self.previewStatus)
        self.previewButton = QtWidgets.QPushButton(self.widget1)
        self.previewButton.setObjectName("previewButton")
        self.horizontalLayout_2.addWidget(self.previewButton)
        self.resultGroup = QtWidgets.QGroupBox(MainWindow)
        self.resultGroup.setGeometry(QtCore.QRect(470, 20, 231, 151))
        self.resultGroup.setObjectName("resultGroup")
        self.resultLabel = QtWidgets.QLabel(self.resultGroup)
        self.resultLabel.setGeometry(QtCore.QRect(20, 30, 191, 101))
        self.resultLabel.setObjectName("resultLabel")

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("Form", " Print controls "))
        self.controlsGroup.setTitle(_translate("Form", " Print control "))
        self.label.setText(_translate("Form", " Number of printed copies :"))
        self.styleCombo.setItemText(0, _translate("Form", "A3"))
        self.styleCombo.setItemText(1, _translate("Form", "A4"))
        self.styleCombo.setItemText(2, _translate("Form", "A5"))
        self.label_2.setText(_translate("Form", " Paper type :"))
        self.printButton.setText(_translate("Form", " Print "))
        self.previewStatus.setText(_translate("Form", " Full screen preview "))
        self.previewButton.setText(_translate("Form", " preview "))
        self.resultGroup.setTitle(_translate("Form", " Operating results "))
        self.resultLabel.setText(_translate("Form", "<html><head/><body><p><br/></p></body></html>"))


class MyMainWindow(QMainWindow, Ui_MainWindow):
    help_signal = QtCore.Signal(str)
    print_signal = QtCore.Signal(list)
    #  Declare a signal with multiple overloaded versions , Includes a band int and str Signal of type parameter , And the belt str Parameter signal 
    preview_signal = QtCore.Signal([int, str], [str])

    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__(parent)
        self.setupUi(self)
        self.init_signal_and_slot()

    def init_signal_and_slot(self):
        self.help_signal.connect(self.show_help_message)
        self.print_signal.connect(self.print_paper)
        self.preview_signal[str].connect(self.preview_paper)
        self.preview_signal[int, str].connect(self.preview_paper_with_args)

        self.printButton.clicked.connect(self.emit_print_signal)
        self.previewButton.clicked.connect(self.emit_preview_signal)

    #  Send preview signal 
    def emit_preview_signal(self):
        if self.previewStatus.isChecked():
            self.preview_signal[int, str].emit(1080, " Full Screen")
        elif not self.previewStatus.isChecked():
            self.preview_signal[str].emit("Preview")

    #  Transmit print signal 
    def emit_print_signal(self):
        print_info = [self.numberSpinBox.value(), self.styleCombo.currentText()]
        self.print_signal.emit(print_info)

    def print_paper(self, print_info):
        self.resultLabel.setText(" Print : " + " Additional copies :" + str(print_info[0]) + "  paper :" + str(print_info[1]))

    def preview_paper_with_args(self, style, text):
        self.resultLabel.setText(str(style) + text)

    def preview_paper(self, text):
        self.resultLabel.setText(text)

    #  Reload keyboard click events 
    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_F1:
            self.help_signal.emit("help message")

    #  Show help messages 
    def show_help_message(self, message):
        self.resultLabel.setText(message)
        self.statusBar().showMessage(message)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = MyMainWindow()
    win.show()
    sys.exit(app.exec())

5、 Use of signals and slots in multithreading

The simplest multithreading  QThread Use

The way is to use QThread function .

Example :QThread Simple combination of function and signal

# -*- coding: utf-8 -*-

import sys
from PySide6.QtCore import *
from PySide6.QtWidgets import *


class MyThread(QThread):
    #  The custom signal parameters are str type 
    custom_signal = Signal(str)

    def __init__(self, parent=None):
        super(MyThread, self).__init__(parent)
        #  Initialization name is empty 
        self.times = None
        self.identity = None

    def set_identity(self, text):
        #  Set the multithread name 
        self.identity = text

    def set_val(self, val):
        #  Receive data , Running multithreading 
        self.times = int(val)
        self.run()

    def run(self):
        #  When the number is greater than 0 And execute code when the name is not empty 
        while self.times > 0 and self.identity:
            #  Send a signal , Trigger the print function , frequency -1
            self.custom_signal.emit(self.identity + '==>' + str(self.times))
            self.times -= 1


class WinForm(QWidget):
    def __init__(self, parent=None):
        super(WinForm, self).__init__(parent)

        #  Create a thread instance and set the name   Variable   Signal and slot 
        self.thread = MyThread()
        self.thread.set_identity('thread1')
        self.thread.custom_signal.connect(self.out_text)
        self.thread.set_val(6)

    #  Print out text 
    def out_text(self, text):
        print(text)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    form = WinForm()
    form.show()
    sys.exit(app.exec())
    pass

Example :

import sys, time
from PySide6.QtCore import (
    Signal, Slot, Qt, QThread
)
from PySide6.QtWidgets import (
    QWidget, QVBoxLayout, QPushButton, QLabel, QApplication
)


class mainWindow(QWidget):
    def __init__(self) -> None:
        super().__init__()

        self.label = QLabel("Hello!")
        self.label.setAlignment(Qt.AlignCenter)
        self.but = QPushButton("Click!")
        self.but.clicked.connect(self.fun)

        self.layout = QVBoxLayout()
        self.layout.addWidget(self.label)
        self.layout.addWidget(self.but)
        self.setLayout(self.layout)
        self.setWindowTitle('Signal Example')
        self.resize(300, 300)
        self.show()

    @Slot()
    def fun(self):
        self.th = Th()
        self.th.timer.connect(self.flushlabel)
        self.th.finish.connect(self.isFinish)
        self.th.start()

    @Slot(int)
    def flushlabel(self, nu):
        self.label.setText(str(nu))

    @Slot(bool)
    def isFinish(self, bo):
        if bo is True:
            self.but.setEnabled(True)
        else:
            self.but.setEnabled(False)


class Th(QThread):
    timer = Signal(int)
    finish = Signal(bool)

    def __init__(self) -> None:
        super().__init__()

    def run(self):
        print('Start Timer')
        self.finish.emit(False)
        for x in range(5):
            self.timer.emit(5 - x)
            time.sleep(1)
        self.finish.emit(True)


if __name__ == '__main__':
    app = QApplication([])
    widgets = mainWindow()
    sys.exit(app.exec())

Use of main threads and sub threads

Sometimes, some time-consuming operations are often performed when developing programs , This will cause the interface to jam , This is also one of the applications of multithreading , In this way, we can create multithreading , Use the main thread to update the interface , Use sub threads to process data in the background , Finally, the results are displayed on the interface

# -*- coding: utf-8 -*-

import sys
import time
from PySide6.QtCore import *
from PySide6.QtWidgets import *


class BackQthread(QThread):
    #  The custom signal is str Parameter type 
    update_date = Signal(str)

    def run(self):
        while True:
            #  Get the current system time 
            data = QDateTime.currentDateTime()
            #  Set the time display format 
            current_time = data.toString('yyyy-MM-dd hh:mm:ss dddd')
            #  Send a signal 
            self.update_date.emit(str(current_time))
            #  Sleep for a second 
            time.sleep(1)


class window(QDialog):
    def __init__(self):
        super(window, self).__init__()
        #  Set title and initial size 
        self.backend = None
        self.setWindowTitle('PyQt5 Examples of real-time interface updates ')
        self.resize(400, 100)
        #  Instantiate the text input box and its initial size 
        self.input = QLineEdit(self)
        self.input.resize(400, 100)
        self.init_ui()

    def init_ui(self):
        #  Instantiate objects 
        self.backend = BackQthread()
        #  The signal is connected to the interface to display the slot function 
        self.backend.update_date.connect(self.handle_display)
        #  Multithreading starts 
        self.backend.start()

    def handle_display(self, data):
        #  Set the text of a single line text box 
        self.input.setText(data)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = window()
    win.show()
    sys.exit(app.exec())

6、 Signal and slot multi window data transmission

stay pyqt During programming , We often encounter the problem of entering or selecting multiple parameters , Write multiple parameters to a window , The main window will look bloated , therefore , It is usually to add a button , Call the dialog , Select parameters in the dialog box , Close the dialog box and return the parameters to the main window
pyqt Provides some standard dialog classes , Used to enter data , Modifying data , Change the settings of the application, etc , Common are QFileDialog,QInputDialog,QColorDialog, QFontDialog etc. , There are two common ways to transfer parameters between different windows , One is to transfer parameters between user-defined dialog boxes through attributes , Another way is to use signals and slots between windows

Example 1: Single window data transmission

For programs with a single window , Changes in one control affect changes in another , This change is very easy to solve by using the relationship between signal and slot

# -*- coding: utf-8 -*-

import sys
import time
from PySide6.QtCore import *
from PySide6.QtWidgets import *


class WinForm(QWidget):
    def __init__(self):
        super(WinForm, self).__init__()
        self.init_ui()

    def init_ui(self):
        #  First create a horizontal slider and Lcd Control 
        lcd = QLCDNumber(self)
        slider = QSlider(Qt.Horizontal, self)

        #  Vertical layout , add controls 
        vbox = QVBoxLayout()
        vbox.addWidget(lcd)
        vbox.addWidget(slider)

        #  Set window layout 
        self.setLayout(vbox)
        #  Set the slider value signal to change the connection Lcd Update 
        slider.valueChanged.connect(lcd.display)

        #  Set the initial position and initial size , Set title 
        self.setGeometry(300, 300, 350, 150)
        self.setWindowTitle(' Signal and slot : Connecting slider LCd')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    form = WinForm()
    form.show()
    sys.exit(app.exec())

Example 2: Multi window data transmission : Call the property

New dialog box sub window properties ,form_QDialog.py

import sys
import time
from PySide6.QtCore import *
from PySide6.QtWidgets import *


class DateDialog(QDialog):
    def __init__(self, parent=None):
        super(DateDialog, self).__init__(parent)
        self.setWindowTitle('DateDialog')

        #  Add controls to layout 
        layout = QVBoxLayout(self)
        self.datetime = QDateTimeEdit(self)
        self.datetime.setCalendarPopup(True)
        self.datetime.setDateTime(QDateTime.currentDateTime())
        layout.addWidget(self.datetime)

        buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)
        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)
        layout.addWidget(buttons)

    def date_time(self):
        return self.datetime.dateTime()

    @staticmethod
    def get_datetime(parent=None):
        dialog = DateDialog(parent)
        result = dialog.exec_()
        date = dialog.date_time()
        return date.date(), date.time(), result == QDialog.Accepted

Create a new main window file form_main.py , Used to call  form_QDialog.py

# -*- coding: utf-8 -*-
# @Author  :  The Buddha bless ,  never  bug
# @Date    : 
# @File    : form_main.py.py
# @Software: PyCharm
# @description : XXX


import sys
from PySide6.QtWidgets import *
from form_QDialog import DateDialog


class WinForm(QWidget):
    def __init__(self, parent=None):
        super(WinForm, self).__init__(parent)
        self.resize(400, 90)
        self.setWindowTitle(' An example of returning a value to the main window when the dialog box closes ')

        self.lineEdit = QLineEdit(self)
        self.btn1 = QPushButton(' Pop-up dialog box 1')
        self.btn1.clicked.connect(self.on_btn1_clicked)

        self.btn2 = QPushButton(' Pop-up dialog box 2')
        self.btn2.clicked.connect(self.on_btn2_clicked)

        grid_layout = QGridLayout(self)
        grid_layout.addWidget(self.lineEdit)
        grid_layout.addWidget(self.btn1)
        grid_layout.addWidget(self.btn2)

    def on_btn1_clicked(self):
        dialog = DateDialog(self)
        result = dialog.exec()
        date = dialog.date_time()
        self.lineEdit.setText(date.date().toString())
        print('\n The return value of the date dialog ')
        print('date=%s' % str(date.date))
        print('time=%s' % str(date.time()))
        print('result=%s' % result)

    def on_btn2_clicked(self):
        date, time, result = DateDialog.get_datetime()
        self.lineEdit.setText(date.toString())
        print('\n  The return value of the date dialog ')
        print('date=%s' % str(date))
        print('time=%s' % str(time))
        print('result=%s' % result)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    form = WinForm()
    form.show()
    sys.exit(app.exec())
    pass

Running results :

Example 3: Multi window data transmission : Signal and slot

For multi window data transfer , Generally, the signal is transmitted through the sub window , The main window captures this signal through the slot function , Then get the data in the signal .

There are two kinds of signals transmitted by the sub window :

  • One is the launch built-in pyqt The signal .
  • One is to transmit customized signals . The advantage of transmitting customized signals is that its parameters can be customized , It can be for int list dict Various types and multiple parameters

Create a sub dialog file , The name here is :form_QDialog.py

# -*- coding: utf-8 -*-

from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *


class DateDialog(QDialog):
    Signal_OneParameter = Signal(str)

    def __init__(self, parent=None):
        super(DateDialog, self).__init__(parent)
        self.setWindowTitle(' child window : Used to transmit signals ')

        #  Adding subassemblies to a layout 
        layout = QVBoxLayout(self)

        self.label = QLabel(self)
        self.label.setText(' The former transmits a built-in signal \n The latter transmits custom signals ')

        self.datetime_inner = QDateTimeEdit(self)
        self.datetime_inner.setCalendarPopup(True)
        self.datetime_inner.setDateTime(QDateTime.currentDateTime())

        self.datetime_emit = QDateTimeEdit(self)
        self.datetime_emit.setCalendarPopup(True)
        self.datetime_emit.setDateTime(QDateTime.currentDateTime())

        layout.addWidget(self.label)
        layout.addWidget(self.datetime_inner)
        layout.addWidget(self.datetime_emit)

        #  Use two button(ok and cancel) Separate connection accept() and reject() Slot function 
        buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
            Qt.Horizontal, self)
        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)
        layout.addWidget(buttons)

        self.datetime_emit.dateTimeChanged.connect(self.emit_signal)

    def emit_signal(self):
        date_str = self.datetime_emit.dateTime().toString()
        self.Signal_OneParameter.emit(date_str)

Create main window form_main.py, Call dialog file  form_QDialog.py


import sys
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
from form_QDialog import DateDialog


class WinForm(QWidget):
    def __init__(self, parent=None):
        super(WinForm, self).__init__(parent)
        self.resize(400, 90)
        self.setWindowTitle(' Examples of signal and slot transfer parameters ')

        self.open_btn = QPushButton(' Acquisition time ')
        self.lineEdit_inner = QLineEdit(self)
        self.lineEdit_emit = QLineEdit(self)
        self.open_btn.clicked.connect(self.open_dialog)

        self.lineEdit_inner.setText(' Time to receive the built-in signal in the sub window ')
        self.lineEdit_emit.setText(' Time of receiving custom signal of sub window ')

        grid = QGridLayout()
        grid.addWidget(self.lineEdit_inner)
        grid.addWidget(self.lineEdit_emit)

        grid.addWidget(self.open_btn)
        self.setLayout(grid)

    def open_dialog(self):
        dialog = DateDialog(self)
        ''' Connect the built-in signal of the sub window with the slot function of the main window '''
        dialog.datetime_inner.dateTimeChanged.connect(self.deal_inner_slot)
        ''' Connect the custom signal of the sub window with the slot function of the main window '''
        dialog.Signal_OneParameter.connect(self.deal_emit_slot)
        dialog.show()

    def deal_inner_slot(self, date):
        self.lineEdit_inner.setText(date.toString())

    def deal_emit_slot(self, date_str):
        self.lineEdit_emit.setText(date_str)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = WinForm()
    form.show()
    sys.exit(app.exec())

7、 Signal and slot And Event handling mechanism

Signals and slots can be said to be high-level encapsulation of event processing mechanism , If events are used to create window controls , Then the signal and slot are used to use this control , Like a button , When we use buttons , Only care about clicked The signal , As for how this button accepts and controls mouse click events , Then send this signal , Don't care , But if you want to reload a button , It's time to care , For example, it can change its behavior : Trigger when the mouse is pressed clicked The signal , Instead of releasing

Common event types

qt Programs are event driven , Every action of it is triggered by an event behind the scenes ,Qt There are many types of events , The common ones are as follows

  • Keyboard events : Press and release the key
  • Mouse events : The movement of the mouse pointer , Press and release the mouse button
  • Drag and drop Events : Drag and drop with the mouse
  • Wheel event : Scroll with the mouse wheel
  • Screen drawing event : Redraw some parts of the screen
  • Timing events : When the timer expires
  • "Event" : Keyboard focus moves
  • Entry and exit events : Move the mouse pointer into Widget Inside , Or move out
  • Mobile event :Widget The position of
  • Size change event :widget Size change of
  • Show and hide Events :widget Show and hide
  • Window events : Whether the window is the current window

There are also some common qt event , such as Socket event , The shear board event , Font change event , Layout change event

Use the method of event handling

pyqt The following is provided 5 A method of event processing and filtering ( From weak to strong ), Only the first two methods are used most frequently

1. Re implement event functions

such as mousePressEvent(),keyPressEvent(),paintEvent(), This is the most common event handling method

2. Re actualize QObject.event()

Generally used in pyqt Without providing a handler for this event , That is, when a new event is added

3. Install event filter

If the QObject call installEventFilter, Is equivalent to this QObject Installed an event filter , about QObject For all events , They are passed to the event filter function first eventFilter in , In this function , We can discard or modify these events , For example, use a custom processing mechanism for the events you are interested in , Use the default event handling mechanism for other events , Because this method will call installEventFilter All of the QObject To filter events , Therefore, if there are many events to filter , It will reduce the performance of the program

4. stay QApplication Install event filters in

This method is more powerful than the previous one ,QApplication The event filter of will capture all QObject event , And the first to get the event , in other words , Before sending the event to any other event filter , Will be sent to QApplication Event filters

5. Re actualize QApplication Of notify() Method

pyqt Use notify To distribute Events , To capture events before any event handler , The only way is to re implement QApplication Of notify(), In practice , This method is only used in debugging

Example : Classic case

Draw the event

Window resizing Events

Mouse release

Mouse movement events

Keyboard press event

heavy load tab key

import sys
from PySide6.QtCore import (QEvent, QTimer, Qt)
from PySide6.QtWidgets import (QApplication, QMenu, QWidget)
from PySide6.QtGui import QPainter


class Widget(QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        #  Initialization data 

        #  Mouse click False
        self.justDoubleClicked = False
        #  Key , The output text , Prompt message is empty 
        self.key = ""
        self.text = ""
        self.message = ""
        #  Set the initial size and position of the window 
        self.resize(400, 300)
        self.move(100, 100)
        #  Set title 
        self.setWindowTitle("Events")
        #  Timer 1 Execute the slot function in seconds 
        QTimer.singleShot(1000, self.give_help)
        #  Avoid the effect of window size redrawing Events , You can put the parameters 0 Change to 3000(3 second ), And then it's running , You can understand the meaning of this line of code .

    def give_help(self):
        self.text = " Please click here to trigger the tracking mouse function "
        #  Redraw events , That is to trigger paintEvent function .
        self.update()

    ''' Re implement the shutdown event '''

    def closeEvent(self, event):
        print("Closed")

    ''' Re implement context menu events '''

    def contextMenuEvent(self, event):
        #  Instantiate menu , Add submenu one two And add shortcut key function , Correlation slot function 
        menu = QMenu(self)
        one_action = menu.addAction("&One")
        two_action = menu.addAction("&Two")
        one_action.triggered.connect(self.one)
        two_action.triggered.connect(self.two)

        #  If message It's empty , perform 
        if not self.message:
            #  Add a split line to the menu 
            menu.addSeparator()
            #  Add from menu three, Correlation slot function 
            threeAction = menu.addAction("Thre&e")
            threeAction.triggered.connect(self.three)
        #  The menu bar appears in the mouse position 
        menu.exec_(event.globalPos())

    ''' Context menu slot function '''

    def one(self):
        self.message = "Menu option One"
        self.update()

    def two(self):
        self.message = "Menu option Two"
        self.update()

    def three(self):
        self.message = "Menu option Three"
        self.update()

    ''' Re implement drawing events '''

    def paintEvent(self, event):
        text = self.text
        i = text.find("\n\n")
        if i >= 0:
            text = text[0:i]

        #  If the keyboard button is triggered , Record the button information in the text information .
        if self.key:
            text += "\n\n You pressed : {0}".format(self.key)

        painter = QPainter(self)

        painter.setRenderHint(QPainter.TextAntialiasing)

        #  Draw the content of the message text 
        painter.drawText(self.rect(), Qt.AlignCenter, text)

        #  If the message text exists, draw the message in the center at the bottom ,5 After seconds, clear the message text and redraw .
        if self.message:
            #  Displays the text at the given coordinates , coordinate , Alignment mode . Text content 
            painter.drawText(self.rect(), Qt.AlignBottom | Qt.AlignHCenter,
                             self.message)
            # 5 The function that triggers the clearing of information after seconds , And redraw the event 
            QTimer.singleShot(5000, self.clear_message)
            QTimer.singleShot(5000, self.update)

    ''' Empty the slot function of message text '''

    def clear_message(self):
        self.message = ""

    ''' Re implement the resize window event '''

    def resizeEvent(self, event):
        self.text = " Size the window to : QSize({0}, {1})".format(
            event.size().width(), event.size().height())
        self.update()

    ''' Re implement the mouse release event '''

    def mouseReleaseEvent(self, event):
        #  If the mouse release is double-click release , Does not track mouse movement 
        if self.justDoubleClicked:
            self.justDoubleClicked = False
        #  If the mouse release is click release , You need to change the state of the tracking function , If you turn on the tracking function, you can track , If you don't turn on the tracking function, you won't track 
        else:
            #  Click the mouse 
            self.setMouseTracking(not self.hasMouseTracking())
            if self.hasMouseTracking():
                self.text = " Turn on the mouse tracking function .\n" + \
                            " Please move the mouse !\n" + \
                            " Click the mouse to turn off this function "
            else:
                self.text = " Turn off mouse tracking .\n" + \
                            " Click the mouse to turn on this function "
            self.update()

    ''' Re implement the mouse movement event '''

    def mouseMoveEvent(self, event):
        #  If there is no mouse double click , perform 
        if not self.justDoubleClicked:
            #  Convert window coordinates to screen coordinates 
            global_pos = self.mapToGlobal(event.pos())
            self.text = """ Mouse position :
             The window coordinates are :QPoint({0}, {1}) 
             The screen coordinates are :QPoint({2}, {3}) """.format(event.pos().x(), event.pos().y(), global_pos.x(), global_pos.y())
            self.update()

    ''' Re implement the mouse double click event '''

    def mouseDoubleClickEvent(self, event):
        self.justDoubleClicked = True
        self.text = " You double clicked the mouse "
        self.update()

    ''' Re implement the keyboard press event '''

    def keyPressEvent(self, event):
        self.key = ""
        if event.key() == Qt.Key_Home:
            self.key = "Home"
        elif event.key() == Qt.Key_End:
            self.key = "End"
        elif event.key() == Qt.Key_PageUp:
            if event.modifiers() & Qt.ControlModifier:
                self.key = "Ctrl+PageUp"
            else:
                self.key = "PageUp"
        elif event.key() == Qt.Key_PageDown:
            if event.modifiers() & Qt.ControlModifier:
                self.key = "Ctrl+PageDown"
            else:
                self.key = "PageDown"
        elif Qt.Key_A <= event.key() <= Qt.Key_Z:
            if event.modifiers() & Qt.ShiftModifier:
                self.key = "Shift+"
            self.key += event.text()
        #  If key Have a character , Not empty , Then draw characters 
        if self.key:
            self.key = self.key
            self.update()
        #  Otherwise, continue to monitor this event 
        else:
            QWidget.keyPressEvent(self, event)

    ''' Re implement other events , Apply to PyQt The event handler is not provided ,Tab Key because it involves focus switching , It will not be passed on to keyPressEvent, therefore , Need to redefine here .'''

    def event(self, event):
        #  If a key is pressed , And the key is tab key 
        if (event.type() == QEvent.KeyPress and
                event.key() == Qt.Key_Tab):
            self.key = " stay event() Capture in Tab key "
            self.update()
            return True
        return QWidget.event(self, event)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = Widget()
    form.show()
    app.exec()

Example 2: Use of filters

The following code means that this filter is only for label1 To deal with the incident , And only handle its mouse press event and mouse release event

import sys

from PySide6.QtGui import *
from PySide6.QtCore import *
from PySide6.QtWidgets import *


class EventFilter(QDialog):
    def __init__(self, parent=None):
        super(EventFilter, self).__init__(parent)
        self.setWindowTitle(' Event filter ')

        #  Instantiate and set four label texts 
        self.label1 = QLabel(' Please click on ')
        self.label2 = QLabel(' Please click on ')
        self.label3 = QLabel(' Please click on ')
        self.labelState = QLabel('test')

        #  Load three pictures 
        self.image1 = QImage('images\cartoon1.ico')
        self.image2 = QImage('images\cartoon2.ico')
        self.image3 = QImage('images\cartoon3.ico')

        self.width = 600
        self.height = 300

        #  Set the initial size 
        self.resize(self.width, self.height)

        #  Use personal leave filter 
        self.label1.installEventFilter(self)
        self.label2.installEventFilter(self)
        self.label3.installEventFilter(self)

        #  Set the window layout and add controls 
        layout = QGridLayout(self)
        layout.addWidget(self.label1, 500, 0)
        layout.addWidget(self.label2, 500, 1)
        layout.addWidget(self.label3, 500, 2)
        layout.addWidget(self.labelState, 600, 1)

    def eventFilter(self, watched, event):
        #  Processing and filtering mechanism for event one 
        if watched == self.label1:
            if event.type() == QEvent.MouseButtonPress:
                mouseEvent = QMouseEvent(event)
                if mouseEvent.buttons() == Qt.LeftButton:
                    self.labelState.setText(' Press the left mouse button ')
                elif mouseEvent.buttons() == Qt.MidButton:
                    self.labelState.setText(' Press the middle mouse button ')
                elif mouseEvent.buttons() == Qt.RightButton:
                    self.labelState.setText(' Press the right mouse button ')

                #  Convert picture size 
                transform = QTransform()
                transform.scale(0.5, 0.5)
                tmp = self.image1.transformed(transform)
                self.label1.setPixmap(QPixmap.fromImage(tmp))
            if event.type() == QEvent.MouseButtonRelease:
                self.labelState.setText(' Release the mouse button ')
                self.label1.setPixmap(QPixmap.fromImage(self.image1))
        return QDialog.eventFilter(self, watched, event)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    dialog = EventFilter()
    app.installEventFilter(dialog)
    dialog.show()
    app.exec()

原网站

版权声明
本文为[Catch the king before the thief]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/187/202207060919582432.html