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 相关文章推荐
Django中的CACHE_BACKEND参数和站点级Cache设置
Jul 23 Python
Python中几种导入模块的方式总结
Apr 27 Python
浅析PHP与Python进行数据交互
May 15 Python
Python中list查询及所需时间计算操作示例
Jun 21 Python
pycharm中成功运行图片的配置教程
Oct 28 Python
Django数据库连接丢失问题的解决方法
Dec 29 Python
python 限制函数执行时间,自己实现timeout的实例
Jan 12 Python
50行Python代码实现视频中物体颜色识别和跟踪(必须以红色为例)
Nov 20 Python
pytorch 移动端部署之helloworld的使用
Oct 30 Python
python读取pdf格式文档的实现代码
Apr 01 Python
OpenCV-Python实现油画效果的实例
Jun 08 Python
Python 中的单分派泛函数你真的了解吗
Jun 22 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
收音机发烧友应当熟知的100条知识
2021/03/02 无线电
在PHP中设置、使用、删除Cookie的解决方法
2013/05/06 PHP
php操作csv文件代码实例汇总
2014/09/22 PHP
php中静态类与静态变量用法的区别分析
2015/01/15 PHP
php计算多个集合的笛卡尔积实例详解
2017/02/16 PHP
Laravel中如何增加自定义全局函数详解
2017/05/09 PHP
php+ajax实现文件切割上传功能示例
2020/03/03 PHP
学习YUI.Ext 第六天--关于树TreePanel(Part 1)
2007/03/10 Javascript
Mootools 1.2教程 函数
2009/09/15 Javascript
让firefox支持IE的一些方法的javascript扩展函数代码
2010/01/02 Javascript
判断iframe是否加载完成的完美方法
2010/01/07 Javascript
页面调用单个swf文件,嵌套出多个方法。
2011/11/21 Javascript
JQuery设置和去除disabled属性的5种方法总结
2013/05/16 Javascript
用javascript判断IE版本号简单实用且向后兼容
2013/09/11 Javascript
js实现点击向下展开的下拉菜单效果代码
2015/09/01 Javascript
bootstrap弹出层的多种触发方式
2017/05/10 Javascript
iview通过Dropdown(下拉菜单)实现的右键菜单
2018/10/26 Javascript
详解mpvue中使用vant时需要注意的onChange事件的坑
2019/05/16 Javascript
用JS实现选项卡
2020/03/23 Javascript
JavaScript实现猜数字游戏
2020/05/20 Javascript
JavaScript实现点击切换验证码及校验
2021/01/10 Javascript
Python中的闭包总结
2014/09/18 Python
Python自动化部署工具Fabric的简单上手指南
2016/04/19 Python
Python简单操作sqlite3的方法示例
2017/03/22 Python
Python实现爬取需要登录的网站完整示例
2017/08/19 Python
python增加矩阵维度的实例讲解
2018/04/04 Python
Python实现繁?转为简体的方法示例
2018/12/18 Python
详解python uiautomator2 watcher的使用方法
2019/09/09 Python
python每5分钟从kafka中提取数据的例子
2019/12/23 Python
pytorch 查看cuda 版本方式
2020/06/23 Python
CSS3的resize属性使用初探
2015/09/27 HTML / CSS
美国受信赖的教育产品供应商:Nest Learning
2018/06/14 全球购物
Baby Tulai澳大利亚:美国婴儿背带品牌
2018/10/15 全球购物
俄罗斯最大的在线珠宝大卖场:Nebo
2019/12/08 全球购物
药学专业大学生自荐信
2013/09/28 职场文书
Vue中使用import进行路由懒加载的原理分析
2022/04/01 Vue.js