pyqt5自定义信号实例解析


Posted in Python onJanuary 31, 2018

本文研究的主要是pyqt5自定义信号实例解析的相关内容,具体介绍如下。

PyQt5已经自动定义了很多QT内建的信号。但是在实际的使用中为了灵活使用信号与槽机制,我们可以根据需要自定义signal。可以使用pyqtSignal()方法定义新的信号,新的信号作为类的属性。

自定义signal说明:

pyqtSignal()方法原型(PyQt官网的定义):

PyQt5.QtCore.pyqtSignal(types[, name[, revision=0[, arguments=[]]]])
Create one or more overloaded unbound signals as a class attribute.

Parameters:
types ? the types that define the C++ signature of the signal. Each type may be a Python type object or a string that is the name of a C++ type. Alternatively each may be a sequence of type arguments. In this case each sequence defines the signature of a different signal overload. The first overload will be the default.

name ? the name of the signal. If it is omitted then the name of the class attribute is used. This may only be given as a keyword argument.

revision ? the revision of the signal that is exported to QML. This may only be given as a keyword argument.

arguments ? the sequence of the names of the signal's arguments that is exported to QML. This may only be given as a keyword argument.
Return type: an unbound signal

新的信号应该定义在QObject的子类中。新的信号必须作为定义类的一部分,不允许将信号作为类的属性在类定义之后通过动态的方式进行添加。通过这种方式新的信号才能自动的添加到QMetaObject类中。这就意味这新定义的信号将会出现在Qt Designer,并且可以通过QMetaObject API实现内省。

通过下面的例子,了解一下关于signal的定义:

from PyQt5.QtCore import QObject, pyqtSignal

class NewSignal(QObject):

  # 定义了一个“closed”信号,该信号没有参数据
  closed= pyqtSignal()

  # 定义了一个"range_changed"信号,该信号有两个int类型的参数
  range_changed = pyqtSignal(int, int, name='rangeChanged')

自定义信号的发射,通过emit()方法类实现,具体参见该函数的原型:

emit(*args)
Parameters: args ? the optional sequence of arguments to pass to any connected slots.

通过下面的例子,了解一下关于emit()的使用:

from PyQt5.QtCore import QObject, pyqtSignal

class NewSignal(QObject):

  # 一个valueChanged的信号,该信号没有参数.
  valueChanged = pyqtSignal()

  def connect_and_emit_valueChanged(self):
    # 绑定信号和槽函数
    self.valueChanged.connect(self.handle_valueChanged)

    # 发射信号.
    self.trigger.emit()

  def handle_valueChanged(self):
    print("trigger signal received")

示例说明:

自定义信号的一般流程如下:

1、定义信号
2、定义槽函数
3、绑定信号和槽
4、发射信号

通过代码示例来了解一下信号的自定义过程:

#-*- coding:utf-8 -*-
'''
defined Signal
'''
__author__ = 'Tony Zhu'
import sys
from PyQt5.QtCore import pyqtSignal, QObject, Qt, pyqtSlot
from PyQt5.QtWidgets import QWidget, QApplication, QGroupBox, QPushButton, QLabel, QCheckBox, QSpinBox, QHBoxLayout, QComboBox, QGridLayout


class SignalEmit(QWidget):
  helpSignal = pyqtSignal(str)
  printSignal = pyqtSignal(list)
  #声明一个多重载版本的信号,包括了一个带int和str类型参数的信号,以及带str参数的信号
  previewSignal = pyqtSignal([int,str],[str])
  def __init__(self):
    super().__init__()    
    self.initUI()


  def initUI(self):      

    self.creatContorls("打印控制:")
    self.creatResult("操作结果:")

    layout = QHBoxLayout()
    layout.addWidget(self.controlsGroup)
    layout.addWidget(self.resultGroup)
    self.setLayout(layout)

    self.helpSignal.connect(self.showHelpMessage)
    self.printSignal.connect(self.printPaper)
    self.previewSignal[str].connect(self.previewPaper)
    self.previewSignal[int,str].connect(self.previewPaperWithArgs) 
    self.printButton.clicked.connect(self.emitPrintSignal)
    self.previewButton.clicked.connect(self.emitPreviewSignal)

    self.setGeometry(300, 300, 290, 150)
    self.setWindowTitle('defined signal')
    self.show()

  def creatContorls(self,title):
    self.controlsGroup = QGroupBox(title)
    self.printButton = QPushButton("打印")
    self.previewButton = QPushButton("预览")
    numberLabel = QLabel("打印份数:")
    pageLabel = QLabel("纸张类型:")
    self.previewStatus = QCheckBox("全屏预览")
    self.numberSpinBox = QSpinBox()
    self.numberSpinBox.setRange(1, 100)
    self.styleCombo = QComboBox(self)
    self.styleCombo.addItem("A4")
    self.styleCombo.addItem("A5")

    controlsLayout = QGridLayout()
    controlsLayout.addWidget(numberLabel, 0, 0)
    controlsLayout.addWidget(self.numberSpinBox, 0, 1)
    controlsLayout.addWidget(pageLabel, 0, 2)
    controlsLayout.addWidget(self.styleCombo, 0, 3)
    controlsLayout.addWidget(self.printButton, 0, 4)
    controlsLayout.addWidget(self.previewStatus, 3, 0)
    controlsLayout.addWidget(self.previewButton, 3, 1)
    self.controlsGroup.setLayout(controlsLayout)

  def creatResult(self,title):
    self.resultGroup = QGroupBox(title)
    self.resultLabel = QLabel("")
    layout = QHBoxLayout()
    layout.addWidget(self.resultLabel)
    self.resultGroup.setLayout(layout)

  def emitPreviewSignal(self):
    if self.previewStatus.isChecked() == True:
      self.previewSignal[int,str].emit(1080," Full Screen")
    elif self.previewStatus.isChecked() == False:
      self.previewSignal[str].emit("Preview")

  def emitPrintSignal(self):
    pList = []
    pList.append(self.numberSpinBox.value ())
    pList.append(self.styleCombo.currentText())
    self.printSignal.emit(pList)

  def printPaper(self,list):
    self.resultLabel.setText("Print: "+"份数:"+ str(list[0]) +" 纸张:"+str(list[1]))

  def previewPaperWithArgs(self,style,text):
    self.resultLabel.setText(str(style)+text)

  def previewPaper(self,text):
    self.resultLabel.setText(text)     

  def keyPressEvent(self, event):

    if event.key() == Qt.Key_F1:
      self.helpSignal.emit("help message")

  def showHelpMessage(self,message):
    self.resultLabel.setText(message)
    #self.statusBar().showMessage(message)


if __name__ == '__main__':

  app = QApplication(sys.argv)
  dispatch = SignalEmit()
  sys.exit(app.exec_())

运行该函数之后的效果如下:

pyqt5自定义信号实例解析

示例说明:

通过一个模拟打印的界面来详细说明一下关于信号的自定义,在打印的时候可以设定打印的分数,纸张类型,触发“打印”按钮之后,将执行结果显示到右侧;通过全屏预览QCheckBox来选择是否通过全屏模式进行预览,将执行结果显示到右侧。
通过点击F1快捷键,可以显示helpMessage信息。

代码分析:

L12~15:

helpSignal = pyqtSignal(str)
  printSignal = pyqtSignal(list)
  #声明一个多重载版本的信号,包括了一个带int和str类型参数的信号,以及带str参数的信号
  previewSignal = pyqtSignal([int,str],[str])

通过pyqtSignal()定义了三个信号,helpSignal ,printSignal ,previewSignal 。其中:

helpSignal 为str参数类型的信号;

printSignal 为list参数类型的信号;

previewSignal为一个多重载版本的信号,包括了一个带int和str类型参数的信号,以及str类行的参数。

self.helpSignal.connect(self.showHelpMessage)
self.printSignal.connect(self.printPaper)
self.previewSignal[str].connect(self.previewPaper)    
self.previewSignal[int,str].connect(self.previewPaperWithArgs)    
 self.printButton.clicked.connect(self.emitPrintSignal)    
self.previewButton.clicked.connect(self.emitPreviewSignal)

绑定信号和槽;着重说明一下多重载版本的信号的绑定,previewSignal有两个版本previewSignal(str),previewSignal(int,str)。由于存在两个版本,从因此在绑定的时候需要显式的指定信号和槽的绑定关系。

具体如下:

self.previewSignal[str].connect(self.previewPaper) self.previewSignal[int,str].connect(self.previewPaperWithArgs)

其中[str]参数的previewSignal信号绑定previewPaper();[int,str]的previewSignal信号绑定previewPaperWithArgs()

L72~76:

def emitPreviewSignal(self):
    if self.previewStatus.isChecked() == True:
      self.previewSignal[int,str].emit(1080," Full Screen")
    elif self.previewStatus.isChecked() == False:
      self.previewSignal[str].emit("Preview")

多重载版本的信号的发射也需要制定对应发射的版本,类似同信号的版定。

L78~82:

def emitPrintSignal(self):
    pList = []
    pList.append(self.numberSpinBox.value ())
    pList.append(self.styleCombo.currentText())
    self.printSignal.emit(pList)

如代码中所示,在信号发射的时候可以传递python数据类型的参数,在本例中传递list类型的参数pList.

L93~96:

def keyPressEvent(self, event):
    if event.key() == Qt.Key_F1:
      self.helpSignal.emit("help message")

通过复写keyPressEvent()方法,将F1快捷键进行功能的拓展。在windows的大部分应用,我们都会使用一些快捷键来快速的完成某些特定的功能。比如F1键,会快速调出帮助界面。那我们就可以复写keyPressEvent()方法来模拟发送所需的信号,来完成我们的对应任务.

注意事项:

1、自定义的信号在init()函数之前定义;
2、自定义型号可以传递,str、int、list、object、float、tuple、dict等很多类型的参数;
3、注意signal和slot的调用逻辑,避免signal和slot之间出现死循环。如在slot方法中继续发射该信号;

总结

以上就是本文关于pyqt5自定义信号实例解析的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

Python 相关文章推荐
python解析模块(ConfigParser)使用方法
Dec 10 Python
Python 2.7.x 和 3.x 版本的重要区别小结
Nov 28 Python
使用Python的Zato发送AMQP消息的教程
Apr 16 Python
Python使用urllib2模块实现断点续传下载的方法
Jun 17 Python
Python实现短网址ShortUrl的Hash运算实例讲解
Aug 10 Python
详谈python http长连接客户端
Jun 12 Python
Django时区详解
Jul 24 Python
python构造函数init实例方法解析
Jan 19 Python
selenium判断元素是否存在的两种方法小结
Dec 07 Python
python迷宫问题深度优先遍历实例
Jun 20 Python
python turtle绘制多边形和跳跃和改变速度特效
Mar 16 Python
python数字图像处理之图像自动阈值分割示例
Jun 28 Python
Python使用flask框架操作sqlite3的两种方式
Jan 31 #Python
pyqt5简介及安装方法介绍
Jan 31 #Python
Python实现的圆形绘制(画圆)示例
Jan 31 #Python
Python Json序列化与反序列化的示例
Jan 31 #Python
Python实现JSON反序列化类对象的示例
Jan 31 #Python
python删除过期log文件操作实例解析
Jan 31 #Python
Python实现的井字棋(Tic Tac Toe)游戏示例
Jan 31 #Python
You might like
PHP快速排序quicksort实例详解
2016/09/28 PHP
Laravel网站打开速度优化的方法汇总
2017/07/16 PHP
PHP获取MySQL执行sql语句的查询时间方法
2018/08/21 PHP
JavaScript 面向对象编程(2) 定义类
2010/05/18 Javascript
S2SH整合JQuery+Ajax实现登录验证功能实现代码
2013/01/30 Javascript
子窗体与父窗体传值示例js代码
2013/08/01 Javascript
Javascript表格翻页效果的具体实现
2013/10/05 Javascript
JS使用post提交的两种方式
2015/12/03 Javascript
JavaScript代码性能优化总结(推荐)
2016/05/16 Javascript
bootstrap实现每隔5秒自动轮播效果
2016/12/20 Javascript
详解vue2 $watch要注意的问题
2017/09/08 Javascript
elemetUi 组件--el-upload实现上传Excel文件的实例
2017/10/27 Javascript
AngularJS中scope的绑定策略实例分析
2017/10/30 Javascript
vue-cli的工程模板与构建工具详解
2018/09/27 Javascript
详解vue中$nextTick和$forceUpdate的用法
2019/12/11 Javascript
vue element和nuxt的使用技巧分享
2021/01/14 Vue.js
[05:02]2014DOTA2 TI中国区预选赛精彩TOPPLAY第三弹
2014/06/25 DOTA
python中模块的__all__属性详解
2017/10/26 Python
python list格式数据excel导出方法
2018/10/31 Python
python中的数据结构比较
2019/05/13 Python
django 通过url实现简单的权限控制的例子
2019/08/16 Python
Python3.6实现根据电影名称(支持电视剧名称),获取下载链接的方法
2019/08/26 Python
Python的几种主动结束程序方式
2019/11/22 Python
python类中super() 的使用解析
2019/12/19 Python
tensorflow模型保存、加载之变量重命名实例
2020/01/21 Python
Python环境管理virtualenv&virtualenvwrapper的配置详解
2020/07/01 Python
十八大闭幕感言
2014/01/22 职场文书
文秘人员工作职责
2014/01/31 职场文书
2014年迎新年活动方案
2014/02/19 职场文书
《孔子拜师》教学反思
2014/02/24 职场文书
联片教研活动总结
2014/07/01 职场文书
幼儿教师小班个人总结
2015/02/05 职场文书
超市采购员岗位职责
2015/04/07 职场文书
楚门的世界观后感
2015/06/03 职场文书
2016七夕情人节广告语
2016/01/28 职场文书
假期读书倡议书3篇
2019/08/19 职场文书