PyQt5中的事件与信号处理

devtools/2024/10/9 13:22:54/

文章目录

    • 1. 简介
      • 1.1事件(Event)
      • 1.2 信号(Signal)与槽(Slot)
      • 1.3 自定义信号
    • 2. 一个信号与槽的简单示例1
    • 3. 一个信号与槽的简单示例2
    • 4. 事件发送者
    • 5. 创建自定义信号
    • 6. 一个简单计算器

1. 简介

在PyQt5中,事件和信号处理是GUI编程的核心概念。事件是指用户操作或系统消息(如鼠标点击、键盘输入、窗口大小变化等),而信号是指对象之间的通信机制,用于在一个事件发生时通知其他对象执行相应的操作。PyQt5提供了丰富的类和方法来处理事件和信号。

1.1事件(Event)

事件是用户与应用程序交互时发生的动作或状态变化,例如点击鼠标、按键盘等。在PyQt5中,每个窗口小部件(widget)都有一个事件处理器(event handler),它用于处理与该小部件相关的事件。

事件处理器是一个函数,它接收一个事件对象作为参数,并根据事件的类型执行相应的操作。常用的事件处理器包括:

  • mousePressEvent():处理鼠标按下事件。
  • mouseReleaseEvent():处理鼠标释放事件。
  • keyPressEvent():处理键盘按下事件。
  • resizeEvent():处理窗口大小变化事件。

以下是一个简单的示例,演示如何在PyQt5中处理鼠标点击事件:

from PyQt5.QtWidgets import QApplication, QLabelclass MyLabel(QLabel):def mousePressEvent(self, event):print("鼠标点击了标签!")app = QApplication([])
label = MyLabel("点击我!")
label.show()
app.exec_()
  • 首先,导入了QApplicationQLabel类,它们分别是QtWidgets模块中用于创建应用程序和标签的类。
  • 接着,定义了一个继承自QLabel的子类MyLabel。在MyLabel类中,重写了mousePressEvent()方法,该方法在鼠标点击事件发生时被调用。当鼠标点击标签时,会在控制台输出消息“鼠标点击了标签!”。
  • 创建了一个QApplication对象,作为整个应用程序的实例。这是每个PyQt5应用程序的必需步骤。
  • 创建了一个MyLabel对象,并传入了一个字符串参数作为标签的文本内容。
  • 调用show()方法显示标签窗口,使其可见。
  • 调用exec_()方法启动应用程序的事件循环,使应用程序保持运行状态,直到用户退出。在此期间,应用程序将等待用户交互事件,例如鼠标点击、键盘输入等。

运行如下图
在这里插入图片描述

鼠标点击窗口里的三个字,就会触发事件,在控制台输出

在这里插入图片描述

1.2 信号(Signal)与槽(Slot)

信号和槽是PyQt5中用于对象之间通信的机制。当一个对象发出信号时,其他对象可以连接到该信号,并在信号触发时执行相应的槽函数。

  • 信号是对象发出的事件,例如按钮被点击、文本框内容变化等。
  • 槽是响应信号的函数,可以是对象的任意方法。

PyQt5中的大多数小部件都有一些内置的信号,例如按钮的clicked信号、文本框的textChanged信号等。可以使用connect()方法将信号连接到槽函数上。

以下是一个示例,演示如何连接按钮的clicked信号到槽函数:

from PyQt5.QtWidgets import QApplication, QPushButtondef on_button_clicked():print("按钮被点击了!")app = QApplication([])
button = QPushButton("点击我!")
button.clicked.connect(on_button_clicked)
button.show()
app.exec_()
  • 这里,我们定义了一个名为on_button_clicked()的函数。这个函数没有参数,当按钮被点击时会被调用,它的作用是在控制台输出消息“按钮被点击了!”。
  • 创建了一个QPushButton对象,并传入了一个字符串参数作为按钮的文本内容。
  • 调用了按钮的clicked信号,并使用connect()方法将其连接到on_button_clicked()函数上。这意味着当按钮被点击时,on_button_clicked()函数会被调用。

运行如下图

在这里插入图片描述

鼠标点击窗口里的三个字,就会触发事件,在控制台输出

在这里插入图片描述

1.3 自定义信号

除了使用内置信号外,还可以自定义信号来实现对象之间的通信。可以使用pyqtSignal()方法创建自定义信号,然后使用emit()方法发出信号。

以下是一个示例,演示如何创建并使用自定义信号:

from PyQt5.QtCore import QObject, pyqtSignalclass MyObject(QObject):my_signal = pyqtSignal(str)def do_something(self):# 发出信号self.my_signal.emit("Hello from custom signal!")def on_custom_signal(value):print("接收到自定义信号:", value)obj = MyObject()
obj.my_signal.connect(on_custom_signal)
obj.do_something()
  • 首先,导入了QObjectpyqtSignal类,它们分别是QtCore模块中用于创建对象和自定义信号的类。
  • 接着,定义了一个名为MyObject的类,它继承自QObject。在MyObject类中,创建了一个名为my_signal的类属性,它是一个pyqtSignal对象,用于定义一个带有一个字符串参数的自定义信号。
  • MyObject类中定义了一个名为do_something()的方法。在这个方法中,调用了self.my_signal.emit()方法发出自定义信号,并传入了字符串参数"Hello from custom signal!"。
  • 接下来,定义了一个名为on_custom_signal()的函数,它有一个参数value,用于接收信号发出的参数。在这个函数中,打印了接收到的自定义信号和传入的参数。
  • 创建了一个MyObject对象,用于发出自定义信号。
  • 调用了对象的my_signal信号,并使用connect()方法将其连接到on_custom_signal()函数上。这样,当MyObject对象发出自定义信号时,on_custom_signal()函数会被调用。
  • 调用了do_something()方法,触发了自定义信号的发出。一旦自定义信号发出,与之连接的槽函数on_custom_signal()就会被调用,打印出"Hello from custom signal!"。

运行上面程序,我们有如下结果

在这里插入图片描述

2. 一个信号与槽的简单示例1

下面是一个简单的示例,展示了如何使用PyQt5创建一个拨动(QDial)和一个LCD数字显示屏(QLCDNumber),当拨动改变时,LCD数字显示屏会实时更新显示拨动的值。

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QDial, QLCDNumberclass DialLCDExample(QWidget):def __init__(self):super().__init__()self.init_ui()def init_ui(self):# 设置窗口标题和大小self.setWindowTitle('拨动与LCD示例')self.setGeometry(100, 100, 300, 200)# 创建垂直布局管理器layout = QVBoxLayout()# 创建拨动和LCD数字显示屏self.dial = QDial()  # 创建QDial对象self.lcd = QLCDNumber()  # 创建QLCDNumber对象# 设置拨动的范围和步长self.dial.setMinimum(0)  # 设置拨动的最小值self.dial.setMaximum(100)  # 设置拨动的最大值self.dial.setValue(50)  # 设置初始值self.dial.setSingleStep(1)  # 设置拨动的步长# 将拨动的valueChanged信号连接到LCD数字显示屏的display槽上self.dial.valueChanged.connect(self.lcd.display)# 将拨动和LCD数字显示屏添加到布局中layout.addWidget(self.dial)layout.addWidget(self.lcd)# 设置窗口的布局为垂直布局管理器self.setLayout(layout)if __name__ == '__main__':app = QApplication(sys.argv)  # 创建应用程序实例window = DialLCDExample()  # 创建窗口实例window.show()  # 显示窗口sys.exit(app.exec_())  # 运行应用程序的事件循环

在上面程序中:

  • QApplication:用于创建应用程序实例,每个PyQt5程序都需要一个。
  • QWidget:所有用户界面对象的基类,这里的窗口继承自QWidget
  • QVBoxLayout:垂直布局管理器,用于管理窗口中的控件布局。
  • QDial:拨动控件,可以让用户通过拨动手柄来选择数值。
  • QLCDNumber:用于显示数字的LCD屏幕控件。
  • init_ui():初始化用户界面的方法,设置窗口标题、大小、布局等。
  • setValue():设置拨动控件的初始值。
  • setSingleStep():设置拨动控件的步长。
  • valueChanged:拨动控件的值变化时发出的信号。
  • connect():将信号连接到槽函数上,当拨动控件的值变化时,调用槽函数更新LCD数字显示屏的值。
  • show():显示窗口。
  • exec_():运行应用程序的事件循环。

运行程序,结果如下

在这里插入图片描述

3. 一个信号与槽的简单示例2

下面是一个简单的PyQt5示例,演示了如何重写keyPressEvent()方法来处理按键事件,当按住上、下、左、右方向键时,窗口中的文本内容会依次在对应方位移动。

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel
from PyQt5.QtCore import Qtclass KeyPressEventExample(QWidget):def __init__(self):super().__init__()self.init_ui()def init_ui(self):# 设置窗口标题和大小self.setWindowTitle('按键事件处理示例')self.setGeometry(100, 100, 300, 200)# 创建一个标签,并将其文本居中显示self.label = QLabel("按住上、下、左、右方向键试试")self.label.setAlignment(Qt.AlignCenter)# 创建垂直布局管理器layout = QVBoxLayout()layout.addWidget(self.label)  # 将标签添加到布局中self.setLayout(layout)  # 设置窗口的布局为垂直布局管理器def keyPressEvent(self, event):# 检测按下的按键key = event.key()# 获取窗口的当前位置current_pos = self.label.pos()# 移动文本内容的方位if key == Qt.Key_Up:self.label.move(current_pos.x(), current_pos.y() - 10)  # 向上移动文本内容elif key == Qt.Key_Down:self.label.move(current_pos.x(), current_pos.y() + 10)  # 向下移动文本内容elif key == Qt.Key_Left:self.label.move(current_pos.x() - 10, current_pos.y())  # 向左移动文本内容elif key == Qt.Key_Right:self.label.move(current_pos.x() + 10, current_pos.y())  # 向右移动文本内容if __name__ == '__main__':app = QApplication(sys.argv)  # 创建应用程序实例window = KeyPressEventExample()  # 创建窗口实例window.show()  # 显示窗口sys.exit(app.exec_())  # 运行应用程序的事件循环

在上面程序中,

  • QApplication:用于创建应用程序实例,每个PyQt5程序都需要一个。
  • QWidget:所有用户界面对象的基类,这里的窗口继承自QWidget
  • QVBoxLayout:垂直布局管理器,用于管理窗口中的控件布局。
  • QLabel:用于显示文本或图像的标签控件。
  • init_ui():初始化用户界面的方法,设置窗口标题、大小、布局等。
  • keyPressEvent():重写了按键事件处理方法,当按下方向键时会调用此方法。
  • event.key():获取按下的按键。
  • Qt.Key_UpQt.Key_DownQt.Key_LeftQt.Key_Right:定义了方向键的键码。
  • pos():获取标签的当前位置。
  • move():移动标签的位置。
  • show():显示窗口。
  • exec_():运行应用程序的事件循环。

运行上面程序,我们会有如下结果

在这里插入图片描述

4. 事件发送者

在PyQt5中,事件发送者(event sender)是指触发事件的对象。当用户与GUI中的控件交互时(例如点击按钮、输入文本等),这些控件会发出相应的事件信号。事件发送者是触发这些信号的对象,可以通过事件对象来获取事件发送者的信息。

以下是一个简单的示例,演示了如何使用事件发送者:

import sys
from PyQt5.QtWidgets import QApplication, QPushButton, QLabel, QVBoxLayout, QWidgetclass EventSenderExample(QWidget):def __init__(self):super().__init__()self.init_ui()def init_ui(self):self.setWindowTitle('事件发送者示例')self.setGeometry(100, 100, 300, 200)layout = QVBoxLayout()self.label = QLabel("等待按钮点击...")layout.addWidget(self.label)self.button1 = QPushButton("按钮1")self.button1.clicked.connect(self.on_button_click)layout.addWidget(self.button1)self.button2 = QPushButton("按钮2")self.button2.clicked.connect(self.on_button_click)layout.addWidget(self.button2)self.setLayout(layout)def on_button_click(self):sender = self.sender()  # 获取事件发送者self.label.setText(f"按钮 {sender.text()} 被点击了")if __name__ == '__main__':app = QApplication(sys.argv)window = EventSenderExample()window.show()sys.exit(app.exec_())

在这个示例中,有两个按钮,当其中任何一个按钮被点击时,标签文本会显示哪个按钮被点击了。在on_button_click()方法中,self.sender()方法用于获取事件发送者,即触发信号的按钮对象。然后可以通过获取到的按钮对象进行相应的操作。

在这里插入图片描述

5. 创建自定义信号

在PyQt5中,可以通过继承自QObject的子类来创建自定义信号。使用pyqtSignal()方法创建自定义信号,并使用emit()方法发出信号。其他对象可以连接到这个自定义信号,并在信号触发时执行相应的槽函数。

下面是一个简单的示例,演示了如何创建和使用自定义信号,这个示例基于1.3里的例子进一步改进:

import sys
from PyQt5.QtCore import QObject, pyqtSignal
from PyQt5.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidgetclass MyObject(QObject):# 创建一个自定义信号my_signal = pyqtSignal(str)def do_something(self):# 发出自定义信号self.my_signal.emit("Hello from custom signal!")class CustomSignalExample(QWidget):def __init__(self):super().__init__()self.init_ui()def init_ui(self):self.setWindowTitle('自定义信号示例')self.setGeometry(100, 100, 300, 200)layout = QVBoxLayout()self.button = QPushButton("点击发出自定义信号")layout.addWidget(self.button)self.setLayout(layout)self.button.clicked.connect(self.on_button_click)def on_button_click(self):obj = MyObject()obj.my_signal.connect(self.on_custom_signal)obj.do_something()def on_custom_signal(self, value):print("接收到自定义信号:", value)if __name__ == '__main__':app = QApplication(sys.argv)window = CustomSignalExample()window.show()sys.exit(app.exec_())

在这个示例中,创建了一个名为MyObject的QObject子类,并在其中定义了一个自定义信号my_signal。在do_something()方法中,通过调用emit()方法来发出自定义信号。

CustomSignalExample窗口中,有一个按钮,当按钮被点击时,会创建MyObject对象,并连接其自定义信号到槽函数on_custom_signal上。然后调用do_something()方法,发出自定义信号。当自定义信号被发出时,槽函数on_custom_signal会被调用,并打印出接收到的自定义信号的值。

运行程序,我们会得到

在这里插入图片描述

点击按钮,会在控制端输出

在这里插入图片描述

6. 一个简单计算器

下面是一个比较复杂的事件与槽的例子,演示了如何使用PyQt5创建一个简单的计算器应用程序。用户可以在文本框中输入两个数字,然后点击按钮执行加法、减法、乘法或除法运算,并将结果显示在另一个文本框中。

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton, QLabelclass CalculatorApp(QWidget):def __init__(self):super().__init__()self.init_ui()def init_ui(self):self.setWindowTitle('简单计算器')self.setGeometry(100, 100, 300, 200)# 创建布局main_layout = QVBoxLayout()input_layout = QHBoxLayout()output_layout = QHBoxLayout()# 创建输入框和标签self.input1 = QLineEdit()self.input2 = QLineEdit()self.operation_label = QLabel()# 创建按钮self.add_button = QPushButton('+')self.sub_button = QPushButton('-')self.mul_button = QPushButton('*')self.div_button = QPushButton('/')# 创建结果显示标签self.result_label = QLabel()# 将输入框和按钮添加到输入布局中input_layout.addWidget(self.input1)input_layout.addWidget(self.input2)input_layout.addWidget(self.operation_label)# 将按钮添加到输出布局中output_layout.addWidget(self.add_button)output_layout.addWidget(self.sub_button)output_layout.addWidget(self.mul_button)output_layout.addWidget(self.div_button)# 将布局添加到主布局中main_layout.addLayout(input_layout)main_layout.addLayout(output_layout)main_layout.addWidget(self.result_label)self.setLayout(main_layout)# 连接按钮的点击事件到槽函数self.add_button.clicked.connect(self.add)self.sub_button.clicked.connect(self.subtract)self.mul_button.clicked.connect(self.multiply)self.div_button.clicked.connect(self.divide)# 定义加法槽函数def add(self):num1 = float(self.input1.text())num2 = float(self.input2.text())result = num1 + num2self.operation_label.setText('+')self.result_label.setText(f'结果:{result}')# 定义减法槽函数def subtract(self):num1 = float(self.input1.text())num2 = float(self.input2.text())result = num1 - num2self.operation_label.setText('-')self.result_label.setText(f'结果:{result}')# 定义乘法槽函数def multiply(self):num1 = float(self.input1.text())num2 = float(self.input2.text())result = num1 * num2self.operation_label.setText('*')self.result_label.setText(f'结果:{result}')# 定义除法槽函数def divide(self):num1 = float(self.input1.text())num2 = float(self.input2.text())if num2 != 0:result = num1 / num2self.operation_label.setText('/')self.result_label.setText(f'结果:{result}')else:self.result_label.setText('除数不能为零')if __name__ == '__main__':app = QApplication(sys.argv)window = CalculatorApp()window.show()sys.exit(app.exec_())

运行上面程序,我们可以得到

在这里插入图片描述


http://www.ppmy.cn/devtools/38907.html

相关文章

山东知识付费问答系统,给孩子学习优秀的辅导班怎么选择?

现在的辅导班越来越多,除了兴趣爱好补习班,还有某一学科辅导,辅导班之所以这么火,是因为很多家长学生有这方面的需求。家长都想要自己的孩子成绩提高,比如数学等,辅导班也就越来越多,这么多辅导…

CSS:min-width作用

min-width作用 介绍用法举例1. 设置元素的最小宽度2. 使用百分比设置最小宽度3. 继承最小宽度 总结 介绍 在Web开发中,min-width 是CSS(层叠样式表)的一个属性,用于设置元素的最小宽度。当元素的宽度小于min-width属性指定的值时…

程序设计——前后端分离实现简单表白墙

文章目录 一、前端页面样式代码二、前后端衔接1. 后端创建 maven 项目2. 针对前后端交互的解释以及后端代码的实现针对 post 请求解释前后端衔接针对 Get 请求解释前后端衔接 3.后端与数据库的联系以及对数据的存取单独封装数据库连接代码解释后端存储 save 数据的代码解释后端…

OpenAI计划下周一宣布对标谷歌搜索的竞品;苹果将使用自有服务器芯片为AI工具提供支持 | 最新快讯

《科创板日报》5月10日讯 今日科创板早报的主要内容还有:行业协会:硅片价格已经脱离供需基本面运行,并朝向非理性方向发展;中芯国际、华虹公司Q1净利同比大降。 【市场动态】 OpenAI计划下周一宣布对标谷歌搜索的竞品 OpenAI计…

基于C++函数基础中的形参与实参

在C中,函数的形参(形式参数)是在函数定义时声明的参数,而实参(实际参数)是在函数调用时传递给函数的值或变量。 形参的作用是定义函数在执行时所需要的输入,它们在函数体内被当做局部变量使用。…

设计模式-观察者模式

作者持续关注 WPS二次开发专题系列,持续为大家带来更多有价值的WPS开发技术细节,如果能够帮助到您,请帮忙来个一键三连,更多问题请联系我(QQ:250325397) 目录 定义 特点 使用场景 优缺点 (1) 优点 (2)…

【DevOps】Ubuntu防火墙配置:如何封禁黑客攻击源IP

在网络安全防护的实践中,及时识别并封锁恶意攻击的IP地址是至关重要的。本文将指导您如何使用Ubuntu系统的防火墙工具有效地封禁那些试图侵入网络的黑客IP。通过详细的步骤和实用的命令,即使是初学者也能轻松掌握如何配置防火墙,增强您的网络…

神经网络中的归一化

我们今天介绍一下神经网络中的归一化方法~ 之前学到的机器学习中的归一化是将数据缩放到特定范围内,以消除不同特征之间的量纲和取值范围差异。通过将原始数据缩放到一个特定的范围内,比如[0,1]或者[-1,1],来消除不同特征之间的量纲和取值范围…