PyQt5 default event handling

1. Introduction
Widget-based applications are driven by events. Clicking the mouse, pressing a button, redrawing a component, and minimizing the window will all generate corresponding events. These events are dealt with correspondingly in order to realize the functions of the program.

2. The event loop of the application program
The event is mainly generated by the window system of the operating system, and the generated event enters an event queue and is processed by the event loop of the application program. The following is the main program structure of a PyQt5 application:

app = QApplication(sys.argv)
mainform = QmyWidget()
mainform.show()
sys.exit(app.exec_())

app is the created application object, and the last executed app.exec_() starts the application's event processing loop . The application will process the events queued in the event queue, and can also perform combined processing on the same events. For example, the redrawing event paintEvent of an interface component, if the same event appears repeatedly in the event queue, the application will merge and process it. Therefore, event processing is an asynchronous processing mechanism .

3. Event types and default event processing functions
In PyQt5, an event is an object represented by the abstract class QEvent . There are many subclasses of QEvent that represent specific events, such as QKeyEvent for key events, QMouseEvent for mouse events, and QPaintEvent for window drawing events.

When an event occurs, PyQt5 will create an event instance object with the corresponding subclass of QEvent according to the specific type of the event, and then pass it to the event() function of the object that generated the event for processing.

Both the QObject class and its subclasses can handle events, but the event processing is mainly used in the form class ( QWidget and its subclasses). The following is the prototype of the event() function of the QObject class:

event(self, <em>e</em>)

The parameter e is the type of QEvent, and the QEvent class mainly has the following three interface functions:
(1) accept() : Indicates that the event receiver accepts the event and processes the event, and the accepted event will not be propagated to the upper container component.
(2) ignore() : Indicates that the event receiver ignores the secondary event, and the ignored event will be propagated to the upper container component.
(3) type() : The type of the returned event is the enumeration type QEvent.Type. This enumeration type consists of more than 100 values, representing more than 100 types of events.

Each value of the enumeration type QEvent.Type corresponds to an event class. For example, the QEvent.KeyPress type represents a key press event, and the corresponding event class is QKeyEvent.

After a class receives an event, it will first trigger its event() function. If the event() function does not do any processing, it will automatically trigger the default event handler.

The QWidget class is the parent class of all interface component classes. It defines the default handlers for various events. For example, the enumeration type of the mouse double-click event is QEvent.MouseButtonDblClick, and the default event handler is mouseDoubleClickEvent(). The function prototype is:

mouseDoubleClickEvent(self, event)

The parameter event is of type QMouseEvent, which is the class corresponding to the mouse type.
QWidget defines a lot of default event processing functions, which will pass an event parameter, but the type of event is determined by the specific event type. The commonly used default event processing functions are shown in the table (only the function name is listed in the table, and the function input parameters are not listed)

default function name trigger timing Parameter event type
mousePressEvent() Triggered when a mouse button is pressed QMouseEvent
mouseReleaseEvent() Fired when the mouse button is released QMouseEvent
mouseMoveEvent() Triggered when the mouse moves QMouseEvent
mouseDoubleClickEvent() Triggered when the mouse is double-clicked QMouseEvent
keyPressEvent() Triggered when a keyboard key is pressed QKeyEvent
keyReleaseEvent() Triggered when a keyboard key is released QKeyEvent
paintEvent() Triggered when the interface needs to be repainted QPaintEvent
closeEvent() Fired when a form is closed QCloseEvent
showEvent() Fired when a window is shown QShowEvent
hideEvent() Fired when a form is hidden QHideEvent
resizeEvent() Triggered when the component changes size, such as when a window changes size QResizeEvent
focusInEvent() Triggered when a component gets keyboard focus, such as a QLineEdit component gets input focus QFocusEvent
focusOutEvent() Triggered when a component loses keyboard focus, such as a QLineEdit component loses input focus QFocusEvent
enterEvent() Triggered when the mouse enters the screen space of the component, such as when the mouse moves over a QPushButton component QEvent
leaveEvent() Triggered when the mouse leaves the component's screen space, such as a QPushButton component QEvent
dragEnterEvent() The drag operation is in progress, triggered when the mouse moves over the component QDragEnterEvent
dragLeaveEvent() The drag operation is in progress, triggered when the mouse moves out of the component QDragLeaveEvent
dragMoveEvent() Triggered when the drag operation is in progress and the mouse moves QDragMoveEvent
dropEvent() Fired when a drag operation is dropped on a component QDropEvent

Users can reimplement these default event handling functions in custom classes inherited from QWidget or its subclasses, so as to achieve some required functions. For example, QWidget does not have a clicked() signal, so the mouse click cannot be processed through signals and slots, but the mouseReleaseEvent() function can be re-implemented to process the mouse click event.

The following example illustrates the default event handling based on the project template widgetApp:
insert image description here

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QMessageBox
from PyQt5.QtCore import pyqtSlot, Qt, QEvent
from PyQt5.QtGui import QPainter, QPixmap

from ui_Widget import Ui_Widget
class QmyWidgrt(QWidget):
	def __init__(self, parent = None):
		super().__init__(parent)	#调用父类构造函数,创建窗体
		self.ui = Ui_Widget()		#创建UI对象
		self.ui.SetupUi(self)		#构造UI

Then in the QmyWidget class, the following default processing functions of some typical events are re-implemented.
(1) paintEvent()
is triggered when the interface needs to be redrawn, and some custom drawing functions can be implemented in this event function. Draw the form background image:

def paintEvent(self, event):
	painter = QPainter(self)
	pic = QPixmap("sea1.jpg")
	painter.drawPixmap(0, 0, self.width(), self.height(), pic)
	super().paintEvent(event)

The function of the function is to draw a picture file sea1.jpg to the entire area of ​​the form, and the brush object painter of the form is used for drawing. The image file sea1.jpg must be in the same directory as the script file that uses it. The last line of statement means to execute the paintEvent() event processing function of the parent class, so that the parent class can perform some built-in operations.

(2) resizeEvent()
is triggered when the window changes size. In this event function, a button btnTest is always placed in the center of the window according to the size of the window.

def resizeEvent(self, event):
	W = self.width()
	H = self.height()
	Wbtn = self.ui.btnTest.width()
	Hbtn = self.ui.btnTest.height()
	self.ui.btnTest.setGeometry((W-Wbtn)/2, (H-Hbtn)/2, Wbtn, Hbtn)

(3) closeEvent()
is triggered when the form is closed. In this event function, a dialog box can be used to ask whether to close the form. The code is as follows:

def closeEvent(self, event):
	dlgTitle = "Question消息框"
	strInfo = "closeEvent事件触发,确定要退出吗?"
	defaultBtn = QMessageBox.NoButton
	result = QMessageBox.question(self, dlgTitle, strInfo, QMessageBox.Yes | QMessageBox.No, defaultBtn)
	if(result == QMessageBox.Yes):
		event.accept()			#窗体可关闭
	else:
		event.ignore()			#窗体不可关闭

The dialog box QMessageBox is used to ask whether to close the form.
insert image description here
The parameter event of the closeEvent(event) function is of type QCloseEvent, and the accept() function of QCloseEvent can be called according to the return result of the dialog box to close the form, while the ignore() function does not close the form.

(4) mousePressEvent()
is triggered when the mouse button is pressed. In this event function, it is judged whether the left mouse button is pressed. If the left button is pressed, the screen coordinates of the mouse cursor are displayed, namely:

def mousePressEvent(self, event):
	pt = event.pos()		#鼠标位置,QPoint
	if(event.button() == Qt.LeftButton):	#鼠标左键按下
		self.ui.LabMove.setText("(x, y) = (%d, %d)" %(pt.x(), pt.y()))
		rect = self.ui.LabMove.geometry()
		self.ui.LabMove.setGeometry(pt.x(), pt.y(), rect.width(), rect.height())
	super().mousePressEvent(event)

The parameter event is the type of QMouseEvent, and QMouseEvent has the following interface functions, which represent the information of the pressed button and the coordinate information of the mouse.

  • button() function: the return value is the enumeration type Qt.MouseButton, indicating which button of the mouse is pressed, and has multiple values ​​such as Qt.NoButton, Qt.LeftButton, Qt.RightButton, and Qt.MidButton.
  • buttons() function: the return value is a value combination of the enumeration type Qt.MouseButton, which can be used to judge when multiple buttons are pressed. For example, the statement for judging when the left and right buttons of the mouse are pressed at the same time is:
if(event.buttons() & Qt.LeftButton) and (event.buttons() & Qt.RightButton):
  • x() function and y() function: the return value is int type; pos() function, the return value is QPoint type. The return values ​​of these two groups of functions represent the relative coordinates of the mouse cursor on the component (widget) that receives this event.
  • localPos() function: The return value is of type QPointF, indicating the relative coordinates of the mouse cursor on the component (widget) or item (item) that receives this event.
  • windowPos() function: The return value is of type QPointF, indicating the relative coordinates of the mouse cursor on the window (window) that receives this event.
  • globalX() function and globalY() function: the return value is int type; globalPos() function, the return value is QPoint type. The return values ​​of these two groups of functions represent the global coordinates of the mouse cursor, that is, the coordinates on the screen.
  • screenPos() function: The return value is of type QPointF, indicating the global coordinates of the mouse cursor on the screen that receives this event.

(5) keyPressEvent() or keyReleaseEvent()
keyPressEvent() is triggered when a key on the keyboard is pressed, and keyReleaseEvent() is triggered when the key is released. The code written for keyPressEvent() is as follows:

def keyPressEvent(self, event):
	rect = self.ui.btnMove.geometry()
	if event.key() in set([Qt.Key_A, Qt.Key_Left]):
		self.ui.btnMove.setGeometry(rect.left() - 20, rect.top(), rect.width(), rect.height())
	elif event.key() in set([Qt.Key_D, Qt.Key_Right]):
		self.ui.btnMove.setGeometry(rect.left() + 20, rect.top(), rect.width(), rect.height())
	elif event.key() in set([Qt.Key_W, Qt.Key_Up]):
		self.ui.btnMove.setGeometry(rect.left, rect.top() - 20, rect.width(), rect.height())
	elif event.key() in set([Qt.Key_S, Qt.Key_Down]):
		self.ui.btnMove.setGeometry(rect.left, rect.top() + 20, rect.width(), rect.height())

The parameter event of the keyPressEvent(event) function is the QKeyEvent type, which has the following two main interface functions, which represent the information of the pressed key.

  • key() function: the return value type is int, indicating the pressed key, which corresponds to the value of the enumeration type Qt.Key. The enumeration type Qt.Key includes enumeration values ​​of all keys on the keyboard, such as Qt.Key_Escape, Qt.Key_Tab, Qt.Key_Delete, Qt.Key_Alt, Qt.Key_F1, Qt.Key_A, etc. (see Qt help documentation for details).
  • modifiers() function: the return value is the value combination of the enumeration type Qt.KeyboardModifier, which represents some keys used for combination, such as Ctrl, Alt, Shift and other keys. For example, the statement to determine whether Ctrl+Q is pressed is as follows:
if(event.key() == Qt.Key_Q) and (event.modifiers() & Qt.ControlModifier):

This program expects that when W, A, S, D or the up, down, left, and right arrow keys are pressed, the button btnMove on the form can move up, down, left, and right. But you will find that when using the keyPressEvent() event function, only W, A, S, and D are valid, and if you use the keyReleaseEvent() function, then W, A, S, D and up, down, left, and right directions keys are valid. This means that no QEvent.KeyPress event will be generated when the up, down, left, and right arrow keys are pressed.

Guess you like

Origin blog.csdn.net/qq_35412059/article/details/127405181