【PySide6】信号(signal)和槽函数(slot),以及事件过滤器
创始人
2024-05-29 21:06:35
0

说明

在PYQT中,父控件可以通过两种方式响应子控件的事件:

  • 通过信号(signal)和槽函数(slot)机制连接子控件和父控件
  • 父控件可以通过设置eventFilter()方法来监听响应子控件的事件

一、信号(signal)和槽函数(slot)

示例

在PYQT中,每个组件都可以发出信号(signal),表示某个事件发生了。父组件可以通过connect()方法将子组件的信号连接到自己的槽函数(slot)中,从而响应这个事件。
举个例子,在一个界面中,可能有一个按钮(btn),当用户点击按钮时,需要将用户的操作记录到日志中。这时,可以在父组件中定义一个槽函数(log),然后将按钮的clicked信号连接到这个槽函数中:

class MyWindow(QWidget):def __init__(self):super().__init__()# 创建一个按钮self.btn = QPushButton('Click me', self)# 将按钮的clicked信号连接到log槽函数中self.btn.clicked.connect(self.log)def log(self):# 记录日志print('Button clicked')

QThread 多线程

在 PyQt 中,可以使用信号和槽机制来实现不同线程之间的通信。在使用 QThread 时,可以将 QThread 的子类化与信号和槽机制结合使用来实现多线程编程。

以下是一个简单的示例,展示了如何在 QThread 中使用信号和槽函数:

from PySide6.QtCore import QThread, Signalclass Worker(QThread):finished = Signal()  # 定义一个信号def __init__(self):super().__init__()def run(self):# 这里可以执行耗时操作self.finished.emit()  # 发射信号class MainWindow(QMainWindow):def __init__(self):super().__init__()self.worker = Worker()self.worker.finished.connect(self.on_finished)  # 连接信号和槽函数def on_finished(self):# 这里可以进行 UI 更新等操作passdef start_work(self):self.worker.start()

在上面的示例中,我们定义了一个 Worker 类,它继承自 QThread 类。Worker 类中定义了一个 finished 信号,用于在耗时操作完成后发射信号。在 MainWindow 类中,我们创建了一个 Worker 对象,并将其 finished 信号连接到 on_finished 槽函数上。在 start_work 函数中,我们启动了 Worker 线程,耗时操作完成后会发射 finished 信号,从而触发 on_finished 槽函数的执行。

以下是另一个简单的示例,展示了如何在 QThread 中使用信号和槽函数:
```python
from PySide6.QtCore import QThread, Signal, Slotclass WorkerThread(QThread):new_data = Signal(str)def __init__(self):super(WorkerThread, self).__init__()def run(self):for i in range(20):data = "Data: " + str(i)self.new_data.emit(data)self.msleep(1000)class MainWindow(QMainWindow):def __init__(self):super(MainWindow, self).__init__()self.worker_thread = WorkerThread()self.worker_thread.new_data.connect(self.on_new_data)self.start_button = QPushButton("Start")self.start_button.clicked.connect(self.worker_thread.start)self.layout = QVBoxLayout()self.layout.addWidget(self.start_button)self.central_widget = QWidget()self.central_widget.setLayout(self.layout)self.setCentralWidget(self.central_widget)@Slot(str)def on_new_data(self, data):print("Received data:", data)

在上面的示例代码中,创建了一个WorkerThread类,该类继承自QThread,并包含一个new_data信号。在run方法中,通过emit方法发送new_data信号。在MainWindow类中,创建了一个WorkerThread实例,并将其new_data信号连接到on_new_data槽函数。当用户单击Start按钮时,调用worker_thread.start方法启动新线程。

在on_new_data槽函数中,打印接收到的数据。注意,on_new_data方法带有一个字符串参数,该参数类型必须与new_data信号的参数类型相同。这是通过在on_new_data方法上添加@Slot(str)装饰器来实现的。

总的来说,在pyside6中使用信号和槽函数来使用QThread非常简单,只需将信号连接到槽函数即可。但请注意要在正确的线程中使用信号和槽函数。如果将信号发射到不同的线程中,可能会导致应用程序崩溃或未定义的行为。

二、事件过滤器

在PySide6中,如果在一个widget中创建了另一个widget,那么新widget默认是不会响应父控件的事件的。如果需要让新widget能够响应控件的事件,可以通过设置事件过滤器来实现。

事件过滤器是一种机制,允许我们在任意widget上监视和过滤所有事件,包括父控件的事件。通过设置事件过滤器,可以将父组件接收到的事件传播到子组件中。

示例代码一,在父控件,子控件分别设置事件过滤器

以下是示例代码:
在这里插入图片描述

import sysfrom PySide6.QtCore import QEvent
from PySide6.QtGui import Qt, QPainter
from PySide6.QtWidgets import QWidget, QApplication, QVBoxLayout, QLabel, QHBoxLayoutclass ChildWidget(QWidget):def __init__(self, parent=None):super().__init__(parent)self.setObjectName('ChildWidget')self.setFixedSize(100, 100)self.label = QLabel("Child")# 子组件布局self.child_layout = QVBoxLayout(self)self.child_layout.addWidget(self.label, 1, alignment=Qt.AlignCenter)def eventFilter(self, obj, event):if obj == self and event.type() == QEvent.MouseButtonPress:print('ChildWidget eventFilter', event)return super().eventFilter(obj, event)# 设置子控件颜色def paintEvent(self, event):painter = QPainter(self)painter.fillRect(self.rect(), Qt.red)class ParentWidget(QWidget):def __init__(self):super().__init__()self.setObjectName('ParentWidget')self.setAutoFillBackground(True)self.setFixedSize(200, 200)# 事件过滤器self.child = ChildWidget(self)self.child.installEventFilter(self)self.installEventFilter(self)# 父组件布局self.parent_layout = QHBoxLayout(self)self.parent_label = QLabel("Parent")self.parent_layout.addWidget(self.child, 1)self.parent_layout.addWidget(self.parent_label, 1, alignment=Qt.AlignCenter)def eventFilter(self, obj, event):if obj == self and event.type() == QEvent.MouseButtonPress:print('ParentWidget eventFilter', event)return self.child.eventFilter(obj, event)if __name__ == '__main__':app = QApplication([])parent = ParentWidget()parent.show()sys.exit(app.exec())

示例代码二,在父控件事件中设置所有子控件的事件

在这里插入图片描述

from PySide6.QtCore import Signal, QObject, QEvent
from PySide6.QtWidgets import QWidget, QApplication, QTextEdit, QVBoxLayout, QPushButton, QHBoxLayoutclass ChildWidget(QWidget):def __init__(self, parent=None):super().__init__(parent)self.setObjectName('ChildWidget')self.layout = QHBoxLayout(self)self.child_button = QPushButton("Child")self.layout.addWidget(self.child_button)class ParentWidget(QWidget):def __init__(self):super().__init__()self.setObjectName('ParentWidget')self.layout = QHBoxLayout(self)# parent_buttonself.parent_button = QPushButton("Parent")self.parent_button.installEventFilter(self)# ChildWidgetself.child = ChildWidget(self)self.child.child_button.installEventFilter(self)self.layout.addWidget(self.child)self.layout.addWidget(self.parent_button)self.layout.stretch(2)def eventFilter(self, obj, event):if obj == self.child.child_button and event.type() == QEvent.MouseButtonPress:print('ChildWidget eventFilter', event)elif obj == self.parent_button and event.type() == QEvent.MouseButtonPress:print('ParentWidget eventFilter', event)return super().eventFilter(obj, event)if __name__ == '__main__':app = QApplication([])parent = ParentWidget()parent.show()app.exec()

相关内容

热门资讯

春节小学三年级作文300字(... 春节小学三年级作文300字 篇一快乐的春节春节是我最喜欢的节日。春节是中国最重要的传统节日,也是全家...
书的字述600字作文(优秀3... 书的字述600字作文 篇一:阅读的魅力阅读是一种独特的体验,它能够带我们进入一个全新的世界,让我们与...
三年级上册写一次游戏活动的作... 三年级上册写一次游戏活动的作文 篇一我最喜欢的游戏——躲猫猫今天,我们班组织了一次非常有趣的游戏活动...
三年级作文400字写大海(最... 三年级作文400字写大海 篇一大海大海,是一个神奇的地方。我喜欢大海,因为它给我带来了无穷的快乐和惊...
快乐的小女孩(推荐4篇) 快乐的小女孩 篇一快乐的小女孩,是一个充满活力和阳光的孩子。她总是带着灿烂的笑容,无论面对什么困难和...
我的好朋友作文三年级300字... 我的好朋友作文三年级300字 篇一我的好朋友我有一个好朋友,他叫小明。我们从小学一年级就是同班同学了...
三年级等我长胡子的时候作文(... 三年级等我长胡子的时候作文 篇一当我还是一个年幼的三年级学生时,我对长大充满了幻想和向往。我时常幻想...
三年级作文250字(精彩6篇... 三年级作文250字 篇一我的暑假生活暑假终于来了!我迫不及待地开始了我美妙的暑假生活。首先,我去了海...
三年级暑假作文300字【优选... 三年级暑假作文300字 篇一我的暑假生活暑假终于来了,我盼望了很久的假期终于到来了。这个暑假,我过得...
三年级难忘的作文不少于250... 篇一:三年级难忘的作文记得那是我三年级的一个阳光明媚的早晨,我正坐在教室里,等待着老师给我们布置作文...
猜猜他是谁三年级作文600字... 猜猜他是谁三年级作文600字9篇 篇一猜猜他是谁我有一个好朋友,他总是戴着一顶红色的帽子,穿着一件蓝...
三年级下册作文文明的一件事(... 三年级下册作文文明的一件事 篇一文明的一件事在我们的日常生活中,有许多小事都可以展现出我们的文明素养...
我是一只丑小鸭作文400字【... 我是一只丑小鸭作文400字 篇一我是一只丑小鸭我是一只丑小鸭,从出生的那一刻起,我就和其他小鸭子不一...
三年级寒假里难忘的事作文20... 三年级寒假里难忘的事作文200字 篇一冬日里的雪人今年寒假,我最难忘的事情就是和爸爸一起堆雪人了。寒...
贪吃的小猫三年级作文300字... 贪吃的小猫三年级作文300字 篇一贪吃的小猫我家养了一只非常贪吃的小猫,它的名字叫小奇。小奇是一只黄...
小学三年级作文:我的英语老师... 小学三年级作文:我的英语老师 篇一我的英语老师是一位非常亲切和蔼的老师,她叫李老师。她总是穿着漂亮的...
纸桥【实用4篇】 纸桥 篇一:探索纸桥的稳定性与创造力纸桥,作为一种常见的手工艺品和科学实验,一直以来都备受人们的喜爱...
我来编童话三年级作文300字... 我来编童话三年级作文300字 篇一小兔子的奇幻冒险从前有一只小兔子,它的名字叫小白。小白是一个非常好...
三年级写景作文300字(优秀... 三年级写景作文300字 篇一梦幻的彩虹今天放学后,我和妈妈一起去了公园。公园里有一座小山,山上有一片...
三年级作文我熟悉的地方(优质... 三年级作文我熟悉的地方 篇一我熟悉的地方是我的家乡。我出生在一个美丽的小城市,那里有着丰富的历史和文...