首页 > 其他分享 >【PySide6】信号(signal)和槽函数(slot),以及事件过滤器

【PySide6】信号(signal)和槽函数(slot),以及事件过滤器

时间:2023-12-22 22:33:16浏览次数:31  
标签:slot __ parent signal PySide6 init data self def

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

标签:slot,__,parent,signal,PySide6,init,data,self,def
From: https://www.cnblogs.com/chinasoft/p/17922487.html

相关文章

  • Signal信号记录
    Signal信号记录在POSIX.1-1990标准中定义的信号列表信号值动作说明SIGHUP1Term终端控制进程结束(终端连接断开)SIGINT2Term用户发送INTR字符(Ctrl+C)触发SIGQUIT3Core用户发送QUIT字符(Ctrl+/)触发SIGILL4Core非法指令(程序错误、试图执行数据......
  • 升讯威在线客服系统的并发高性能数据处理技术:超强的 SignalR
    我在业余时间开发维护了一款免费开源的升讯威在线客服系统,也收获了许多用户。对我来说,只要能获得用户的认可,就是我最大的动力。最近客服系统成功经受住了客户现场组织的压力测试,获得了客户的认可。客户组织多名客服上线后,所有员工同一时间打开访客页面疯狂不停的给在线客服发消......
  • covariance matrix in signal processing
    cross-covarianceInthecaseofcomplexrandomvariables,thecovarianceisdefinedslightlydifferentlycomparedtorealrandomvariables.Forcomplexrandomvariables(Z_1)and(Z_2),thecovarianceisdefinedas:\[\text{Cov}(Z_1,Z_2)=E[(Z_1-......
  • 使用JS和SignalR完成双向通信
    写在前面:看官网介绍,听开发者朋友的感受,SignalR对websocket等多个长连接协议进行了封装,提供了多种方法,能够适应很多场合和复杂情况。单纯论简单的web长连接,它确实没有js/nodejs版的websocket直观、简单。微软的风格,一来就高大上,不知道又会劝退多少人,会不会把自己玩死。我帮你简单......
  • 使用Python和Qt6(PySide6)创建GUI应用1简介
    1简介在本书从GUI开发的基本原理逐步过渡到使用PySide6创建您自己的、功能齐全的桌面应用程序。1.1GUI简史图形用户界面(GUIGraphicalUserInterface)历史悠久,可追溯到20世纪60年代。斯坦福大学的NLS(ON-Line系统引入了鼠标和窗口概念,并于1968年首次公开展示。随后,施乐公司......
  • Extraneous children found when component already has explicitly named default sl
    下述代码会报错:Extraneouschildrenfoundwhencomponentalreadyhasexplicitlynameddefaultslot.Thesechildrenwillbeignored.<el-table-columnprop="goodsState"label="商品状态"width="120"/><template#default="......
  • 通过.NET Core+Vue3 实现SignalR即时通讯功能
    .NETCore和Vue3结合使用SignalR可以实现强大的实时通讯功能,允许实时双向通信。在这个示例中,我们将详细说明如何创建一个简单的聊天应用程序,演示如何使用.NETCoreSignalR后端和Vue3前端来实现实时通讯功能。步骤1:准备工作确保你已经安装了以下工具和环境:.NETCore......
  • Fatal signal 11 (SIGSEGV) at 0x0000130f (code=1), thread xxx (Thread-xx)
    导致应用程序崩溃问题分析与解决:--复现--分析--解决最后先展示与问题相关的代码片:09-0413:26:32.826F/libc(572):Fatalsignal11(SIGSEGV)at0x0000130f(code=1),xxxx844(Thread-46)09-0413:26:32.936I/DEBUG(103):*************************......
  • On Manipulating Signals of User-Item Graph A Jacobi Polynomial-based Graph Colla
    目录概符号说明MotivationJGCF代码GuoJ.,DuL,ChenX.,MaX.,FuQ.,HanS.,ZhangD.andZhangY.Onmanipulatingsignalsofuser-itemgraph:Ajacobipolynomial-basedgraphcollaborativefiltering.KDD,2023.概利用JacobiConvolution来区分高中低频信号......
  • Qt blockSignals
    有时我们需要,控件不接收信号,可以使用blockSignals 当设置为true时,QObject对象[子类]不会发出信号1、函数原型1boolQObject::blockSignals(boolblock)2Ifblockistrue,signalsemittedbythisobjectareblocked(i.e.,emittingasignalwillnotinvokeanythin......