PyQt5中重要的概念:信号与槽

PyQt中信号与槽概念定义如下(网络上引用的):

信号(signal)和槽(slot)是Qt的核心机制,也是在PyQt编程中对象之间进行通信的机制。在创建事件循环之后,通过建立信号和槽的连接就可以实现对象之间的通信。当信号发射(emit)时,连接的槽函数将会自动执行。

所谓内置信号与槽的使用。是指在发射信号时,使用窗口控件的函数,而不是自定义的函数。信号与槽的连接方法是通过QObject.signal.connect将一个QObject的信号连接到另一个QObject的槽函数。

信号与槽有三种使用方法,第一种是内置信号与槽的使用,第二种是自定义信号与槽的使用,第三种是装饰器的信号与槽的使用。

python 装饰器详解
【Python】*args**kwargs的用法【最全详解】

官方网站:PyQt API中信号与槽详细解释

内置信号与槽的使用

参考文章:Python Qt GUI设计:信号与槽的使用方法(基础篇---7)

Qt Designer中提供了一些最基础的信号和槽设置方法,在实际的项目开发中,信号和槽最佳的使用方式是Qt Designer和编程相结合,才能提高开发效率。




生成python代码,

自定义信号与槽的使用

不适用内置信号与槽,而使用自定义信号与槽。自定义信号与槽是指在发射信号时,不使用窗口控件的函数,而是使用自定义的函数(简单地说,就是使用pyqtSignal类实例发射信号)。

使用方法示例如下:
PyQt5自定义信号与槽带示例讲解

关键代码:

设置信号事件:signal_single_link = pyqtSignal(str,str,str) #定义下载单条链接的信号参数(文件名,文件大小,文件进度)

定义槽函数:

python 复制代码
def showSingalInfo(self,file_name,file_size,file_progress):
        self.label_txt_path.setText('文件名:'+file_name+'文件大小:'+file_size+'文件进度:'+file_progress)

使用connect()函数,绑定槽函数:self.signal_single_link.connect(self.showSingalInfo)

发送信号给槽,使用emit()函数:self.signal_single_link.emit(str(name),str(file_size),str(formatFloat§))

上述自定义信号与绑定槽操作的作用是下载过程中(单开一个线程实现下载过程),传进度返回给主线程(UI主界面是主线程)中的label控件显示

使用装饰器pyqtSlot定义信号与槽

官方网站:PyQt API中信号与槽详细解释

@pyqtSlot()有两种使用情况。文章:PyQt5 随笔:信号与槽的两种使用方法:@pyqtSlot() 和 connect()


@pyqtSlot()是这种方式的修饰关键词,他表明下面函数是信号槽函数

一个控件同时要写多个信号与槽函数时,只需要写一遍@pyqtSlot()关键词,中间可以有其他函数隔开。

引用自文章:PyQt 5信号与槽的几种高级玩法

PyQt5 连接信号与自定义槽函数,解决槽函数重复执行的问题

Qt for Python 信号和槽的使用详解,比较好理解使用装饰器生成信号事件的文章,但文章是使用PySide2来写 Qt 程序。

有的读者可能注意到,我们一直没有解释下面这行代码的含义:

QMetaObject.connectSlotsByName(QObject)

事实上,它是在PyQt 5中根据信号名称自动连接到槽函数的核心代码。通过前面章节中的例子可以知道,使用pyuic5命令生成的代码中会带有这么一行代码,接下来对其进行解释。

这行代码用来将QObject中的子孙对象的某些信号按照其objectName连接到相应的槽函数。这句话读起来有些拗口,这里举个例子进行简单说明。以上面例子中的代码为例:

假设代码QtCore.QMetaObject.connectSlotsByName(self)已经执行,则下面的代码:

python 复制代码
@QtCore.pyqtSlot()    
def on_okButton_clicked(self):
    print( "单击了OK按钮")

会被自动识别为下面的代码(注意,函数中去掉了on,因为on会受到connectSlotsByName的影响,加上on运行时会出现问题):

python 复制代码
def __init__(self, parent=None):
        self.okButton.clicked.connect(self.okButton_clicked)
def okButton_clicked(self):
    print("单击了OK按钮")

信号与槽的断开与连接

使用disconnect()函数可以解除信号与槽函数的绑定。

python 复制代码
from PyQt5.QtCore import QObject , pyqtSignal

class SignalClass(QObject):

     # 声明无参数的信号
    signal1 = pyqtSignal()

     # 声明带一个int类型参数的信号
    signal2 = pyqtSignal(int)

    def __init__(self,parent=None):
        super(SignalClass,self).__init__(parent)

        # 将信号signal1连接到sin1Call和sin2Call这两个槽函数
        self.signal1.connect(self.sin1Call)
        self.signal1.connect(self.sin2Call)

        # 将信号signal2连接到信号signal1
        self.signal2.connect(self.signal1)

        # 发射信号
        self.signal1.emit()
        self.signal2.emit(1)

        # 断开signal1、signal2信号与各槽函数的连接
        self.signal1.disconnect(self.sin1Call)
        self.signal1.disconnect(self.sin2Call)
        self.signal2.disconnect(self.signal1)

        # 将信号signal1和signal2连接到同一个槽函数sin1Call
        self.signal1.connect(self.sin1Call)
        self.signal2.connect(self.sin1Call)

         # 再次发射信号
        self.signal1.emit()
        self.signal2.emit(1)

    def sin1Call(self):
        print("signal-1 emit")

    def sin2Call(self):
        print("signal-2 emit")

if __name__ == '__main__':  
    signal = SignalClass()

运用自定义信号与槽方法的实际场景

运用自定义信号与槽方法的实际场景:信号和槽一般用于多个窗口之间传递信息, 或者前后端传递信息。

参考文章:大爽pyqt5笔记&教程 三 信号和槽 Signals & Slots 实现窗口跳转、返回、恢复、传参

使用lambda或者functools中的partial函数实现自定义参数的传递

python 中的functools.partial 使用方法

参考文章:python GUI库图形界面开发之PyQt5信号与槽的高级使用技巧(自定义信号与槽)详解与实例

python 复制代码
import sys
from PyQt5.QtWidgets import *
from functools import partial
class WinForm(QMainWindow):
  def __init__(self,parent=None):
    super(WinForm, self).__init__(parent)
    #实例化两个按钮
    button1=QPushButton('Button1')
    button2=QPushButton('Button2')
    #todo 第一种方法
    #单击信号关联槽函数,利用Lanbda表达式传递一个参数
    # button1.clicked.connect(lambda :self.onButtonClick(1))
    # button2.clicked.connect(lambda :self.onButtonClick(2))
    #
    #todo 第二种方法
    button1.clicked.connect(partial(self.onButtonClick, 1))
    button2.clicked.connect(partial(self.onButtonClick, 2))
    #实例化窗口
    main=QWidget()
    #设置窗口的布局,并向其中添加控件
    layout=QHBoxLayout(main)
    layout.addWidget(button1)
    layout.addWidget(button2)
    #设置为中央控件
    self.setCentralWidget(main)
  def onButtonClick( self,n ):
    #弹窗信息提示框,输出被点击的信息
    print("Button {0}".format(n))
    QMessageBox.information(self,'信息提示框','Button {0}'.format(n))
if __name__ == '__main__':
  app=QApplication(sys.argv)
  form=WinForm()
  form.show()
  sys.exit(app.exec_())

代码分析

重点解释

使用lambda表达式传递按钮数字给槽函数,当然还可以传递其他东西,甚至是按钮本身

button1.clicked.connect(lambda :self.onButtonClick(1))

button2.clicked.connect(lambda :self.onButtonClick(2))

另一种方法是使用functools中的partial函数

button1.clicked.connect(partial(self.onButtonClick, 1))

button2.clicked.connect(partial(self.onButtonClick, 2))

相关推荐
炬火初现34 分钟前
Etcd的安装与使用
数据库·etcd
IT猿手43 分钟前
2025最新群智能优化算法:云漂移优化(Cloud Drift Optimization,CDO)算法求解23个经典函数测试集,MATLAB
开发语言·数据库·算法·数学建模·matlab·机器人
雷渊1 小时前
深入分析理解mysql的MVCC
java·数据库·面试
Paparazi灬1 小时前
RocksDB写流程各种场景下的处理逻辑和线程交互时序
数据库
神经星星1 小时前
【vLLM 教程】使用 TPU 安装
数据库·人工智能·机器学习
꧁坚持很酷꧂2 小时前
QT登录系统界面
开发语言·qt
hjehheje2 小时前
clickhouse查询效率低
数据库·人工智能
七七powerful2 小时前
ClickHouse 中出现 DB::Exception: Too many parts 错误
java·前端·数据库
Linux运维老纪3 小时前
Python实战项目(‌Hands-on Python Project)
开发语言·数据库·python·sql·mysql·云计算·运维开发
小林熬夜学编程3 小时前
【MySQL】第十五弹---全面解析事务:定义、起源、版本支持与提交方式
android·linux·服务器·开发语言·数据库·mysql