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生成随机数的方法
Jan 14 Python
python改变日志(logging)存放位置的示例
Mar 27 Python
python写的ARP攻击代码实例
Jun 04 Python
Python中Iterator迭代器的使用杂谈
Jun 20 Python
python中hashlib模块用法示例
Oct 30 Python
python如何使用正则表达式的前向、后向搜索及前向搜索否定模式详解
Nov 08 Python
使用python实现BLAST
Feb 12 Python
Linux下Pycharm、Anaconda环境配置及使用踩坑
Dec 19 Python
Ubuntu下Anaconda和Pycharm配置方法详解
Jun 14 Python
Python实现计算对象的内存大小示例
Jul 10 Python
Django调用支付宝接口代码实例详解
Apr 04 Python
django实现日志按日期分割
May 21 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 mysql 判断update之后是否更新了的方法
2012/01/10 PHP
PHP构造函数与析构函数用法示例
2016/09/28 PHP
PHP在linux上执行外部命令的方法
2017/02/06 PHP
JQuery动画animate的stop方法使用详解
2014/05/09 Javascript
javascript定时器完整实例
2015/02/10 Javascript
Easyui form combobox省市区三级联动
2016/01/13 Javascript
jQuery解决IE6、7、8不能使用 JSON.stringify 函数的问题
2016/05/31 Javascript
Bootstrap禁用响应式布局的实现方法
2017/03/09 Javascript
最通俗易懂的javascript变量提升详解
2017/08/05 Javascript
通过button将form表单的数据提交到action层的实例
2017/09/08 Javascript
vue封装一个简单的div框选时间的组件的方法
2019/01/06 Javascript
vue实现下拉加载其实没那么复杂
2019/08/13 Javascript
Node4-5静态资源服务器实战以及优化压缩文件实例内容
2019/08/29 Javascript
微信小程序加载机制及运行机制图解
2019/11/27 Javascript
jquery实现吸顶导航效果
2020/01/08 jQuery
vue.js+ElementUI实现进度条提示密码强度效果
2020/01/18 Javascript
Python输出带颜色的字符串实例
2017/10/10 Python
[原创]pip和pygal的安装实例教程
2017/12/07 Python
python实现图像识别功能
2018/01/29 Python
OpenCV+python手势识别框架和实例讲解
2018/08/03 Python
python爬虫之验证码篇3-滑动验证码识别技术
2019/04/11 Python
在Pytorch中使用样本权重(sample_weight)的正确方法
2019/08/17 Python
使用Matplotlib 绘制精美的数学图形例子
2019/12/13 Python
详解Scrapy Redis入门实战
2020/11/18 Python
NIHAOMARKET官方海外旗舰店:意大利你好华人超市
2018/01/27 全球购物
JSF面试题:Jsf中导航的标签是什么
2013/04/20 面试题
非常详细的C#面试题集
2016/07/13 面试题
就业推荐表自我鉴定
2013/10/29 职场文书
购房意向书
2014/08/30 职场文书
纪律教育学习心得体会
2014/09/02 职场文书
商业用房租赁协议书
2014/10/13 职场文书
2015年社区服务活动总结
2015/03/25 职场文书
餐厅收银员岗位职责
2015/04/07 职场文书
写给纪委的违纪检讨书
2015/05/05 职场文书
《雪域豹影》读后感:父爱的伟大
2019/12/23 职场文书
Nginx部署vue项目和配置代理的问题解析
2021/08/04 Servers