浅谈pyqt5中信号与槽的认识


Posted in Python onFebruary 17, 2019

一、介绍

信号(Signal)和槽(Slot)是Qt中的核心机制,也是PyQt变成中对象之间进行通信的机制

在pyqt5中,每一个QObject对象和pyqt中所有继承自QWidget的控件都支持信号和槽

当信号发射时,连接槽函数将会自动执行,pyqt5中信号与槽通过connect()函数连接起来的。

在pyqt5中信号主要分两类:

1.内置信号(详细参考各个组件)
2.自定义信号(主要用于组件之间数据的传递与窗口交互)

二、内置信号的简单介绍

使用connect()方法将信号与槽函数绑定在一起,使用disconnect()函数将信号与槽解除绑定

1、按钮点击事件(举例)

import sys
from PyQt5.Qt import *


class Window(QWidget):
  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.setWindowTitle('按钮事件')
    self.resize(500, 500)
    self.move(400, 200)
    self.btn = QPushButton('按钮', self)
    self.init_ui()

  def init_ui(self):
    self.btn.resize(100, 30)
    self.btn.move(100, 50)

    self.btn.clicked.connect(self.btn_hand)

  def btn_hand(self):
    print('按钮点击了')


if __name__ == "__main__":
  app = QApplication(sys.argv)
  window = Window()
  window.show()
  sys.exit(app.exec_())

2、如果连接的事件要传递参数直接使用lambda函数

...
def init_ui(self):
  self.btn.resize(100, 30)
  self.btn.move(100, 50)

  self.btn.clicked.connect(lambda: self.btn_hand(1))

def btn_hand(self, flag):
  print('按钮点击了:{}'.format(flag))
...

三、自定义信号

1、最基本无参数的信号与槽

import sys
from PyQt5.Qt import *


class SignalObj(QObject):
  """
  定义一个信号的类
  """
  # 自定义一个信号
  sendMsg = pyqtSignal()

  def __init__(self):
    super().__init__()

  def run(self):
    self.sendMsg.emit()


class Window(QWidget):
  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.setWindowTitle('自定义事件')
    self.resize(500, 500)
    self.move(400, 200)
    self.btn = QPushButton('按钮', self)
    self.send = SignalObj()
    # 将事件与槽建立关联
    self.send.sendMsg.connect(self.slot_hand)
    self.init_ui()

  def init_ui(self):
    # 系统中自带的事件与槽函数建立连接
    self.btn.clicked.connect(self.btn_hand)

  def btn_hand(self):
    self.send.run()

  @staticmethod
  def slot_hand():
    print('我是自定义的槽函数')


if __name__ == "__main__":
  app = QApplication(sys.argv)
  window = Window()
  window.show()
  sys.exit(app.exec_())

2、信号中发射出数据

import sys
from PyQt5.Qt import *


class SignalObj(QObject):
  """
  定义一个信号的类
  """
  # 自定义一个信号,注意这个地方定义约束发送出去的参数类型,下面要一致
  sendMsg = pyqtSignal(str)

  def __init__(self):
    super().__init__()

  def run(self):
    self.sendMsg.emit('hello')


class Window(QWidget):
  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.setWindowTitle('自定义事件')
    self.resize(500, 500)
    self.move(400, 200)
    self.btn = QPushButton('按钮', self)
    self.send = SignalObj()
    # 将事件与槽建立关联
    self.send.sendMsg.connect(self.slot_hand)
    self.init_ui()

  def init_ui(self):
    # 系统中自带的事件与槽函数建立连接
    self.btn.clicked.connect(self.btn_hand)

  def btn_hand(self):
    self.send.run()

  @staticmethod
  def slot_hand(msg):
    print(f'我是自定义的槽函数:{msg}')


if __name__ == "__main__":
  app = QApplication(sys.argv)
  window = Window()
  window.show()
  sys.exit(app.exec_())

3、对于发送多种不同数据类型的事件

import sys
from PyQt5.Qt import *


class SignalObj(QObject):
  """
  定义一个信号的类
  """
  # 自定义一个信号,注意这个地方定义约束发送出去的参数类型,下面要一致
  sendMsg = pyqtSignal([str], [int])

  def __init__(self):
    super().__init__()

  def run(self):
    self.sendMsg[str].emit('hello')
    self.sendMsg[int].emit(999)


class Window(QWidget):
  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.setWindowTitle('自定义事件')
    self.resize(500, 500)
    self.move(400, 200)
    self.btn = QPushButton('按钮', self)
    self.send = SignalObj()
    # 将事件与槽建立关联(这个地方你要接收那个数据类型的事件)
    self.send.sendMsg[int].connect(self.slot_hand)
    self.init_ui()

  def init_ui(self):
    # 系统中自带的事件与槽函数建立连接
    self.btn.clicked.connect(self.btn_hand)

  def btn_hand(self):
    self.send.run()

  @staticmethod
  def slot_hand(msg):
    print(f'我是自定义的槽函数:{msg}')


if __name__ == "__main__":
  app = QApplication(sys.argv)
  window = Window()
  window.show()
  sys.exit(app.exec_())

四、使用装饰器信号与槽

1、使用格式

@PyQt5.QtCore.pyqtSlot(参数)
def on_发送者对象名称_发射信号名称(self,参数):
 pass

2、注意点,使用装饰器必须定义两个东西

QMetaObject.connectSlotsByName(self)

给需要绑定事件的定义一个id(self.btn.setObjectName('名称'))

3、按钮的普通事件

...
class Window(QWidget):
  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.setWindowTitle('装饰器信号与槽')
    self.resize(500, 500)
    self.move(400, 200)
    self.btn = QPushButton('按钮', self)
    self.init_ui()

  def init_ui(self):
    self.btn.clicked.connect(self.btn_hand)
    
  @staticmethod
  def btn_hand():
    print('使用connect点击了按钮')
...

4、使用装饰器后的事件

...
class Window(QWidget):
  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.setWindowTitle('装饰器信号与槽')
    self.resize(500, 500)
    self.move(400, 200)
    self.btn = QPushButton('按钮', self)
    self.init_ui()
    # 要在加载组件后使用
    QMetaObject.connectSlotsByName(self)

  def init_ui(self):
  # 这个地方定义的名字直接在下面使用
    self.btn.setObjectName('btn')

  @pyqtSlot()
  def on_btn_clicked(self):
    print('使用装饰器点击了按钮')
...

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python基于有道实现英汉字典功能
Jul 25 Python
详解Python3中的Sequence type的使用
Aug 01 Python
详解在Python程序中自定义异常的方法
Oct 16 Python
深入学习Python中的装饰器使用
Jun 20 Python
Python 安装setuptools和pip工具操作方法(必看)
May 22 Python
Python实现按学生年龄排序的实际问题详解
Aug 29 Python
Django权限机制实现代码详解
Feb 05 Python
Python 使用with上下文实现计时功能
Mar 09 Python
解决win64 Python下安装PIL出错问题(图解)
Sep 03 Python
django框架用户权限中的session缓存到redis中的方法
Aug 06 Python
python获得命令行输入的参数的两种方式
Nov 02 Python
最新版 Windows10上安装Python 3.8.5的步骤详解
Nov 28 Python
Laravel+Dingo/Api 自定义响应的实现
Feb 17 #Python
详解pandas库pd.read_excel操作读取excel文件参数整理与实例
Feb 17 #Python
Python线程之定位与销毁的实现
Feb 17 #Python
Pandas读取并修改excel的示例代码
Feb 17 #Python
Python实现去除列表中重复元素的方法总结【7种方法】
Feb 16 #Python
Python字符串逆序输出的实例讲解
Feb 16 #Python
强悍的Python读取大文件的解决方案
Feb 16 #Python
You might like
东芝TOSHIBA RP-F11电路分析
2021/03/02 无线电
深入理解PHP原理之错误抑制与内嵌HTML分析
2011/05/02 PHP
php number_format() 函数通过千位分组来格式化数字的实现代码
2013/08/06 PHP
WordPress中查询文章的循环Loop结构及用法分析
2015/12/17 PHP
PHP迭代器和迭代的实现与使用方法分析
2018/04/19 PHP
js返回上一页并刷新代码整理
2012/12/21 Javascript
JavaScript Serializer序列化时间处理示例
2014/07/31 Javascript
jquery获得同源iframe内body下标签的值的方法
2014/09/25 Javascript
Javascript学习笔记之函数篇(五) : 构造函数
2014/11/23 Javascript
原生Ajax 和jQuery Ajax的区别示例分析
2014/12/17 Javascript
jQuery插件制作之参数用法实例分析
2015/06/01 Javascript
javascript获取网页宽高方法汇总
2015/07/19 Javascript
JS数字千分位格式化实现方法总结
2016/12/16 Javascript
关于vue中 $emit的用法详解
2018/04/12 Javascript
解决循环中setTimeout执行顺序的问题
2018/06/20 Javascript
详解vue的数据劫持以及操作数组的坑
2019/04/18 Javascript
基于form-data请求格式详解
2019/10/29 Javascript
vue中el-input绑定键盘按键(按键修饰符)
2020/07/22 Javascript
[01:51]开启你的城市传奇 完美世界城市挑战赛开始报名
2018/10/09 DOTA
python实现同时给多个变量赋值的方法
2015/04/30 Python
深入理解Python对Json的解析
2017/02/14 Python
对python借助百度云API对评论进行观点抽取的方法详解
2019/02/21 Python
使用PyOpenGL绘制三维坐标系实例
2019/12/24 Python
python pandas移动窗口函数rolling的用法
2020/02/29 Python
python异步Web框架sanic的实现
2020/04/27 Python
解决python虚拟环境切换无效的问题
2020/04/30 Python
用CSS3和table标签实现一个圆形轨迹的动画的示例代码
2019/01/17 HTML / CSS
TheFork葡萄牙:欧洲领先的在线餐厅预订平台
2019/05/27 全球购物
德尔福集团DELPHI的笔试题
2012/02/22 面试题
师生聚会感言
2014/01/26 职场文书
工业设计毕业生自荐信
2014/04/13 职场文书
城市创卫标语
2014/06/17 职场文书
民政局副局长民主生活会个人对照检查材料
2014/09/19 职场文书
房屋分割离婚协议书范本
2014/12/01 职场文书
银行招聘自荐信
2015/03/06 职场文书
解决mysql问题:由于找不到MSVCR120.dll,无法继续执行代码
2021/06/26 MySQL