https://blog.csdn.net/qq_25262697/article/details/129374905

说明
在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')
1
2
3
4
5
6
7
8
9
10
11
12
13
QThread 多线程
在 PyQt 中,可以使用信号和槽机制来实现不同线程之间的通信。在使用 QThread 时,可以将 QThread 的子类化与信号和槽机制结合使用来实现多线程编程。

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

from PySide6.QtCore import QThread, Signal

class 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 更新等操作
pass

def start_work(self):
self.worker.start()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
在上面的示例中,我们定义了一个 Worker 类,它继承自 QThread 类。Worker 类中定义了一个 finished 信号,用于在耗时操作完成后发射信号。在 MainWindow 类中,我们创建了一个 Worker 对象,并将其 finished 信号连接到 on_finished 槽函数上。在 start_work 函数中,我们启动了 Worker 线程,耗时操作完成后会发射 finished 信号,从而触发 on_finished 槽函数的执行。

以下是另一个简单的示例,展示了如何在 QThread 中使用信号和槽函数:
```python
from PySide6.QtCore import QThread, Signal, Slot

class 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)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
在上面的示例代码中,创建了一个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 sys

from PySide6.QtCore import QEvent
from PySide6.QtGui import Qt, QPainter
from PySide6.QtWidgets import QWidget, QApplication, QVBoxLayout, QLabel, QHBoxLayout

class 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())

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
示例代码二,在父控件事件中设置所有子控件的事件

from PySide6.QtCore import Signal, QObject, QEvent
from PySide6.QtWidgets import QWidget, QApplication, QTextEdit, QVBoxLayout, QPushButton, QHBoxLayout

class 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_button
self.parent_button = QPushButton("Parent")
self.parent_button.installEventFilter(self)
# ChildWidget
self.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()
————————————————
版权声明:本文为CSDN博主「KmBase」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_25262697/article/details/129374905

【PySide6】信号(signal)和槽函数(slot),以及事件过滤器的更多相关文章

  1. qt信号signal和槽slot机制

    内容: 一.概述 二.信号 三.槽 四.信号与槽的关联 五.元对象工具 六.程序样例 七.应注意的问题 信号与槽作为QT的核心机制在QT编程中有着广泛的应用,本文介绍了信号与槽的一些基本概念.元对象工 ...

  2. Qt中信号(signal)和槽(slot)的几种关联方法

    声明,个人总结,不一定正确! 1.最常见的,使用connect语句.比如:connect(btnSend,SIGNAL(clicked()),this,SLOT(clear()); 2.在 .ui设计 ...

  3. 第15.16节 PyQt(Python+Qt)入门学习:PyQt中的信号(signal)和槽(slot)机制以及Designer中的使用

    老猿Python博文目录 老猿Python博客地址 一.引言 前面一些章节其实已经在使用信号和槽了,但是作为Qt中最重要的机制也是Qt区别与其他开发平台的重要核心特性,还是非常有必要单独介绍. 二.信 ...

  4. 第四章 、PyQt中的信号(signal)和槽(slot)机制以及Designer中的使用

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.引言 前面章节其实已经在使用信号和槽了,但是作为Qt中最重要的机制也是Qt区别与其他开发平台的重 ...

  5. qt的信号与槽函数

    关联: bool connect ( const?QObject?*?sender, const?char?*?signal, const QObject * receiver, const char ...

  6. Boost 信号与槽,获取槽函数返回值,使用占位参数传递信号携带的参数

    test1: 展示了, 1 信号与槽的基本使用,    2 要获取槽函数的返回值时的注意事项 #if 1 /* 参考blog https://www.cnblogs.com/jiayayao/p/62 ...

  7. PyQt学习随笔:槽函数获取信号发送对象的方法

    在PyQt中,相似控件发送的信号可以每个控件信号对应一个槽函数,也可以将相似控件的相同信号对应到一个槽函数,但如果槽函数相同,怎么区分信号是谁发送的呢?那就是在信号函数中使用sender()函数获取信 ...

  8. PyQt Designer中连接信号和槽时为什么只能连接控件自己的信号和槽函数?

    老猿在学习ListView组件时,想实现一个在ListView组件中选中一个选择项后触发消息给主窗口,通过主窗口显示当前选中的项的内容. 进入QtDesigner后,设计一个图形界面,其中窗口界面使用 ...

  9. PyQt Designer中带参数的信号为什么匹配不到带参数的槽函数?

    老猿在学习ListView组件时,想实现一个在ListView组件中选中一个选择项后触发消息给主窗口,通过主窗口显示当前选中的项的内容. 进入QtDesigner后,设计一个图形界面,其中窗口界面使用 ...

  10. Qt 的线程与事件循环——可打印threadid进行观察槽函数到底是在哪个线程里执行,学习moveToThread的使用)

    周末天冷,索性把电脑抱到床上上网,这几天看了 dbzhang800 博客关于 Qt 事件循环的几篇 Blog,发现自己对 Qt 的事件循环有不少误解.从来只看到现象,这次借 dbzhang800 的博 ...

随机推荐

  1. 做思维导图?chatmoney轻轻松松拿下

    本文由 ChatMoney团队出品 嘿,各位职场朋友们 是不是常常对着密密麻麻的笔记感到焦虑呢? 想整理却无从下手? 别怕,ChatmoneyAI知识库来拯救你的整理困难症啦! 咱们都知道,思维导图是 ...

  2. 你应该懂的AI大模型(三)之 RAG

    从本篇开始笔者会尽量多使用一些英文缩写和单词,不是笔者为了装X,是为了大家在后面遇到的时候不至于被别人装到. 一.什么是RAG 1.1 大模型的局限性 大模型的知识不是实时的,比如现在<藏海传& ...

  3. 致谢每一位ChunJun Contributor!这里有一份礼物等你领取!

    作为一个批流统一的数据集成框架,秉承着易用.稳定.高效的目标,ChunJun于2018年4月29日在Github上将内核源码正式开放. 从还被叫作FlinkX,写下第一行代码开始,ChunJun已经走 ...

  4. C++ list容器学习总结

    ----------------------------list 链表是由一系列的结点组成,结点包含两个域,一个数据域,一个指针域 链表内存是非连续的 添加和删除元素 其时间复杂度都为常数项,不需要移 ...

  5. C# 遍历Enum( 枚举)

    Type enumType = typeof(Domain.Models.Entitys.PermissionEntity.PermissionTypeEnum);                   ...

  6. Excel SUMPRODUCT函数用法(乘积求和,分组排序)

    SUMPRODUCT函数是Excel中功能比较强大的一个函数,可以实现sum,count等函数的功能,也可以实现一些基础函数无法直接实现的功能,常用来进行分类汇总,分组排序等 SUMPRODUCT 函 ...

  7. Genymotion虚拟机启动时get no IP address的解决方法汇总

    "Genymotion虚拟机启动时get no IP address"这个问题一直困扰了我很多天,我在网上也试了不少方法,今天终于成功打开了,太兴奋了. 鉴于网上各种方法比较分散, ...

  8. 使用 ETL 工具对神舟通用数据库进行数据抽取与转换的实操技巧

    在当今的数字化时代,企业面临着数据孤岛的问题,需要将分散在不同系统和数据库中的数据进行整合,以实现数据的统一管理和分析.神州通用作为企业常用的数据库之一,数据处理与转换过程中,数据集成的前期准备工作尤 ...

  9. MySQL 19 为什么我只查一行的语句,也执行这么慢?

    有些情况下,"查一行"也会执行特别慢,今天就看看什么情况会出现这个现象. 如果MySQL本身有很大压力,导致数据库服务器CPU占有率很高或IO利用率很高,这种情况所有语句的执行都可 ...

  10. Kafka为什么吞吐量大,速度快?

    前言 根据个人的经历,无论在工作中,还是即将要经历的面试,MQ这部分是肯定要了解的,虽然之前工作中一直使用Kafka但是一些详细的细节知识还是了解的不深,所以这次总结一波. Kafka为什么吞吐量这么 ...