Pyqt6&Pyside6 信号与槽详解
信号与槽
要实现控件功能的联动和交互操作,比如点击按钮后执行某个动作。对按钮功能的定义,是通过信号(signal)与槽(slot)机制实现的。信号与槽是PySide6编程的基础,也是Qt的一大创新,有了信号与槽的编程机制,在PySide6中处理界面上各个控件的交互操作时变得更加直观和简单。
信号:信号是指从QObject类继承的控件(窗口、按钮、文本框、列表框等)在某个动作下或状态发生改变时发出的一个指令或一个信息,例如一个按钮被单击(clicked)、右击一个窗口(customContextMenuRequested)、一个输入框中文字的改变(textChanged)等,当这些控件的状态发生变化或者外界对控件进行输入时,让这些控件发出一个信息,来通知系统其某种状态发生了变化或者得到了外界的输入,以便让系统对外界的输入进行响应。
槽:槽是系统对控件发出的信号进行的响应,或者产生的动作,通常用函数来定义系统的响应或动作,因此也叫做“槽函数”。例如对于单击“计算”按钮,按钮发出被单击的信号,然后编写对应的函数,当控件发出信号时,就会自动执行与信号关联的函数。
信号与槽的关系可以是一对一,也可以是多对多,即一个信号可以关联多个槽函数,一个槽函数也可以接收多个信号。PySide6已经为控件编写了一些信号和槽函数,使用前需要将信号和槽函数进行连接,另外用户还可以自定义信号和自定义槽函数。
内置信号与内置槽的连接
PySide6对控件已经定义的信号和槽可以在Qt Designer中查看。启动Qt Designer创建一个MainWindow.ui文件,在窗口上拖放一个新的Push Button按钮,并将objectName改成btnClose,将text设置成“关闭”。然后单击工具栏上的“编辑信号/槽”按钮,进入信号和槽的编辑界面,按住Shift键的同时,用鼠标左键拖拽“关闭”按钮到窗口的空白区,这时会出现一个红色线和接地符号,松开鼠标,弹出“配置连接”对话框。
勾选“显示从QWidget继承的信号和槽”,这时对话框的左边列表框中显示按钮的所有已定义信号,右边列表框中显示窗口所有的槽函数。这里左边选择按钮的clicked()信号,右边选择窗口的close()函数,单击OK按钮,就建立了按钮的单击信号(clicked)和窗口的关闭(close)的连接。
按ESC键退出信号/槽编辑状态。另外一种建立信号和槽的方法是使用“信号/槽编辑器”。在Qt Designer的右下角的“信号/槽编辑器”上单击+按钮,双击发送者下的<发送者>,找到btnClose按钮,双击信号下的<信号>,找到clicked(),双击接收者下的<接收者>,找到Form,双击槽下的<槽>,找到close(),这样就建立了信号和槽的连接。如果要删除信号和槽的连接,应先选中信号槽,然后单击-按钮。
将ui文件编译成py文件,打开生成的py文件,可以发现在py中增加了一行新代码self.btnClose.clicked.connect(Form.close),用控件信号的connect()方法将信号和函数进行了连接,注意被连接的槽函数不需要带括号。
self.signalName.connect(receiver.slotName)
添加一个main.py,添加如下代码,运行main.py:
from PySide6.QtWidgets import QApplication, QMainWindow
from Ui_MainWindow import Ui_MainWindow
import sys
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.show()
app = QApplication(sys.argv)
w = MainWindow()
app.exec()
当pushButton被点击,窗口被关闭。
内置信号与自定义槽函数的连接
1.自动关联内置信号的自定义槽函数
将ui文件编译成py文件之后,可以看到py文件中出现下面的语句:
QMetaObject.connectSlotsByName(MainWindow)
这行代码的作用是使用PySide6的元对象QMetaObject在窗口上搜索所有从QObject类继承的控件,将控件的信号自动与槽函数根据名称objectName进行匹配,这是自定义的槽函数只要满足下面的格式,就能实现内置信号与自定义槽函数的关联:
@Slot()
def on_objectName_signalName(self, signalParameter):
函数语句
@Slot()
修饰符用于指定随后的函数是槽函数;
def
为函数定义关键词;
on
为函数名的前缀,必须要有;
objectName
是控件的objectName
属性名称,例如前面的“pushButton”按钮时给按钮设置的属性名称是btnClose;
signalName
是控件的信号名称,如按钮的clicked信号;
signalParameter
是信号传递过来的参数,例如一个checkBox是否处于勾选状态,对checkBox可以定义def on_checkBox_toggled(self,checked)
自动关联槽函数,自动接收来自checkBox的toggled(bool)的信号,其中checked是形参,表示toggled(bool)信号传递的状态。
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton
from PySide6.QtCore import QSize, Slot, QMetaObject
import sys
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.resize(QSize(400, 400))
self.btn = QPushButton("点击后查看控制台")
self.btn.setObjectName("maxBtn") # 2.设置这个控件的objectName
# maxBtn.clicked.connect(self.on_maxBtn_Clicked) # 手动关联槽函数
self.setCentralWidget(self.btn)
QMetaObject.connectSlotsByName(self)
# 1.使用PySide6的元对象QMetaObject在窗口上搜索所有从QObject类继承的控件,
# 将控件的信号自动与槽函数根据名称objectName进行匹配
# 是必须的,否则自动关联无法生效
@Slot() # 3.槽参数类型修饰符
def on_maxBtn_clicked(self): # 4.自动关联槽函数
print("自定义槽函数")
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec()
首先,一定要设置好控件的setObjectName,然后要添加QMetaObject.connectSlotsByName(self)
,否则无法实现自动关联。然后用@Slot修饰自定义的槽函数。运行程序,点击按钮,控制台会打印“自定义槽函数”。
2.重载型信号的处理
在Qt Designer中查询一个控件的信号时,会发现有些控件有多个名字相同但是参数不同的信号。例如对于按钮有clicked()和clicked(bool)两种信号,一种不需要传递参数的信号,另一种传递布尔型参数的信号。这种信号名称相同、参数不同的信号称为重载(overload)型信号。对于重载型信号定义自动关联槽函数时,需要在槽函数前加修饰符@Slot(type)
声明是对哪个信号定义槽函数,其中type是信号传递的参数类型。例如如果对按钮的clicked(bool)信号定义自动关联槽函数,需要在槽函数前加入@Slot(bool)进行修饰;如果对按钮的clicked()信号定义自动关联槽函数,需要在槽函数前加入@Slot()进行修饰。需要注意的是,在使用@Slot(type)修饰符前,应提前用from PySide6.QtCore import Slot
语句导入槽函数。
3.手动关联内置信号的自定义槽函数
除了使用控件内置信号定义自动连接的槽函数外,还可以将控件内置信号手动连接到其他函数上,这时需要用到信号的connect()
方法。
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton
from PySide6.QtCore import QSize, Slot, QMetaObject
import sys
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.resize(QSize(400, 400))
self.btn = QPushButton("点击后查看控制台")
self.btn.clicked.connect(self.btn_click) # 手动关联槽函数
self.setCentralWidget(self.btn)
def btn_click(self):
print("自定义槽函数")
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec()
同样的使用connect
也能实现相同的功能。
自定义信号
只有继承自QObject的类才可以定义信号。自定义信号可以不带参数,也可以带参数,可以带1个参数,也可以带多个参数。参数类型是任意的,如整数(int)、浮点数(float)、布尔(bool)、字符串(str)、列表(list)、元组(tuple)和字典(dict)等。参数类型需要在定义信号时进行声明。自定义信号通常需要在类属性位置用Signal
类来创建,使用Signal前需要用from PySide6.QtCore import Signal
语句导入Signal
类。
1. 自定义信号的定义方式
定义非重载型信号:
signalName = Signal(type1, type2, ...)
定义重载型信号:
signalName = Signal((type1,), (type2,), ...)
signalName
为信号名称;
Signal()
用于创建信号实例对象,type
为信号发送时附带的数据类型,这里数据类型不是形参也不是实参,只是类型的声明,参数类型任意,需根据实际情况确定,()
表示重载信号,如果重载信号不带参数,则只使用()
,不用带type。注意重载型信信号传入的参数是类型名构成的元组。
信号有连接connect()
、发送emit()
和断开disconnect()
属性。对于重载型信号,在进行连接、发送和断开时要使用signalName[type]
形式操作。第一个信号可以直接使用signalName
的形式。
下面是创建不同信号的示例:
from PySide6.QtCore import QObject, Signal
class signalDefinition(QObject): # 只有继承自QObject的类才可以定义信号
signal_none = Signal() # 无参数的信号
signal_int = Signal(int) # 带整数参数的信号
signal_float = Signal(float) # 带浮点数参数的信号
signal_str = Signal(str) # 带字符串参数的信号
signal_list = Signal(list) # 带列表参数的信号
signal_dict = Signal(dict) # 带字典参数的信号
signal_int_float_str = Signal(int, float, str) # 带整数、浮点数、字符串参数的信号
signal_r2 = Signal((int,), (str,)) # 创建重载型信号,相当于创建了2个信号
signal_r3 = Signal(
(
int,
str,
),
(str,),
(list,),
) # 创建重载型信号,相当于创建了3个信号
signal_r = Signal((), (bool)) # 创建重载型信号,一个不带参数,另一个带布尔型参数
def __init__(self, parent=None):
super().__init__(parent)
self.signal_none.connect(self.slot_none) # 信号与槽的连接
self.signal_list.connect(self.slot_list)
self.signal_r2[int].connect(
self.slot_signal_r2_1
) # overload型信号的第一个信号可以不指定类型
self.signal_r2[str].connect(
self.slot_signal_r2_2
) # overload型信号的第一个信号可以不指定类型
self.signal_none.emit() # 发送信号
self.signal_list.emit([1, 2, 3, 4])
self.signal_r2[int].emit(1000)
self.signal_r2[str].emit("信号重载Str")
def slot_none(self): # 自定义槽函数
print("slot_none emit")
def slot_list(self, list):
for i in list:
print(i)
def slot_signal_r2_1(self, v: int):
print(v)
def slot_signal_r2_2(self, s: str):
print(s)
signalDefinition()
运行结果:
slot_none emit
1
2
3
4
1000
信号重载Str
本文作者:Apostle浩
本文链接:https://www.cnblogs.com/holychan/p/18188165
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步