Learn Python PyQt

PyQt events

This article mainly introduces PyQt5 daily must learn events and signals related information, has some reference value, interested partners can refer to

In this section we will explore how PyQt5’s events and signals are implemented in the application.

Book: Create Desktop Apps with Python PyQt5

Events

All GUI applications are event-driven. Application events are generated primarily from users, but they can also be generated by other means, such as an Internet connection, a window manager, or a timer. When we call the exec_() method of the application, the application enters the main loop. The main loop detects various events and sends them to the event object.

In the event model, there are three participants.

  • event source
  • event object
  • event target

An event source is a change in the state of an object that generates an event. An event object (event) is an object that encapsulates a state change in the event source. The event target is the object that wants to be notified. The event source object represents the task of processing an event to the event target.

PyQt5 uses a unique signal and slot mechanism to handle events. Signals and slots are used for communication between objects, and when a particular event occurs, the signal is fired. The slot can be any Python call. The connection to the slot is called while the signal is transmitting.

Signals & slots

Here’s a simple example to demonstrate PyQt5’s signal and slot.

import sys

from PyQt5.QtWidgets import (QApplication, QWidget, QSlider, QLCDNumber, QVBoxLayout)
from PyQt5.QtCore import Qt

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
        
    def initUI(self):
       lcd = QLCDNumber(self)
       sld = QSlider(Qt.Horizontal, self)
       vbox = QVBoxLayout()
       vbox.addWidget(lcd)
       vbox.addWidget(sld)
       self.setLayout(vbox)
       sld.valueChanged.connect(lcd.display)
       self.setGeometry(250, 250, 250, 150)
       self.setWindowTitle('Events demo') 
       self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

In our example, QtGui.QLCDNumber and QtGui.QSlider will be used. we change the LCD numbers by dragging the slider.

sld.valueChanged.connect(lcd.display)

Here, the slider’s valueChanged signal is connected to the LCD’s display (display) slot.

A transmitter is an object that sends a signal. The receiver is the object that receives the signal. What slots is the method of feedback to the signal.

pyqt events signals slots

Overwrite the system event handler. You can use any key to fire an event.
In the example below the escape key triggers an event that quits the program.

import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtCore import Qt

class Example(QWidget):

    def __init__(self):
        super().__init__()
        self.initUI()
        
    def initUI(self):
        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('PyQt events with keyboard') 
        self.show()
        
    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Escape:
            self.close()
    
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

In our example, we reimplement the keyPressEvent() event handler.

def keyPressEvent(self, e):
    if e.key() == Qt.Key_Escape:
        self.close()
    

If we press the Esc key on the keyboard, the application terminates.

Book: Create Desktop Apps with Python PyQt5

Event sender event send

To facilitate differentiation of multiple event sources connected to the same event target, the sender() method can be used in PyQt5.

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton

class Example(QMainWindow):

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

    def initUI(self):
        btn1 = QPushButton('One', self)
        btn1.move(30, 50)
        btn2 = QPushButton('Two', self)
        btn2.move(150, 50)
        btn1.clicked.connect(self.buttonClicked)
        btn2.clicked.connect(self.buttonClicked)
        self.statusBar()
        self.setGeometry(300, 300, 300, 150)
        self.setWindowTitle('Window') 
        self.show()

    def buttonClicked(self):
        sender = self.sender()
        self.statusBar().showMessage(sender.text() + ' changed')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

In our example there are two buttons. Both buttons are connected to the buttonClicked() method and we respond to the clicked button by calling the sender() method.

btn1.clicked.connect(self.buttonClicked)
btn2.clicked.connect(self.buttonClicked)

The two buttons are connected to the same slot.

def buttonClicked(self):
    sender = self.sender()
    self.statusBar().showMessage(sender.text() + ' changed')

We determine the signal source by calling the sender() method. In the application’s status bar, the label of the button that was pressed is displayed.

pyqt button click event

Customized emission signals

An object created from a QObject can signal. In the following example, we’ll look at how we can customize the signal sent.

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import pyqtSignal, QObject
 
class Communicate(QObject):
    closeApp = pyqtSignal()
 
class Example(QMainWindow):

    def __init__(self):
        super().__init__()
        self.initUI()
    def initUI(self):
        self.c = Communicate()
        self.c.closeApp.connect(self.close)
        self.setGeometry(300, 300, 300, 150)
        self.setWindowTitle('Mouse events') 
        self.show()
    
    def mousePressEvent(self, event):
        self.c.closeApp.emit()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

We create a new signal called closeApp. This signal is emitted by the mouse press event. This signal is connected to the close() slot in QMainWindow.

class Communicate(QObject):
    closeApp = pyqtSignal()

Creates a Communicate class inherited from QObject, which has a property of the pyqtSignal() class.

self.c = Communicate()
self.c.closeApp.connect(self.close)

Connect our custom closeApp signal to the close() slot in QMainWindow.

def mousePressEvent(self, event):
    self.c.closeApp.emit()

The CloseApp signal is emitted (emit) when our mouse clicks in the program window: application termination.

Book: Create Desktop Apps with Python PyQt5