捐助郴维网
感谢您对郴维网的支持,你的支持将是郴维网持续发展的动力!
二维码
×
当前位置:郴维网 >Pyqt5 > 正文
3 2018.04

自定义信号

点击次数:1470 更新时间:2018-4-3 12:52:23  【打印此页

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
'''

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.createControls("打印控制:")
        self.createResult("操作结果:")

        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 createControls(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 createResult(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_())

运行该函数之后的效果如下: 
说明: 这里写图片描述

示例说明: 
通过一个模拟打印的界面来详细说明一下关于信号的自定义,在打印的时候可以设定打印的分数,纸张类型,触发“打印”按钮之后,将执行结果显示到右侧;通过全屏预览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类行的参数。

L30~36:

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()

L73~77:

    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")

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

L79~83:

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

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

L95~97:

    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方法中继续发射该信号;

Tips
郴维网为您提供各类专业服务:
软件开发,电脑配件销售,WIFI路由器销售,上门电脑维修,上门安装系统,系统安装,软、硬件安装,电脑除尘清灰,显示器维修,WIFI安装调试,服务器维护,数据恢复,密码破解,网络布线,网络检修,打印机维修,打印机加碳粉,苹果电脑安装系统,苹果电脑安装双系统,监控安装维护,电脑外包,笔记本电脑维修,餐饮、美容行业软件安装 等。。。。。。
点击次数:1470 更新时间:2018-4-3 12:52:23  【打印此页

上一条:信号与槽机制

下一条:基本布局管理

关键词推荐:郴州电脑城 郴州电脑维修公司 维修电脑公司 郴州软件开发 上门电脑维修 上门安装系统 笔记本电脑维修 郴州打印机维修 打印机加碳粉 电脑安装双系统 苹果电脑双系统 液晶显示器维修 联想笔记本维修 联想笔记本维修电话 戴尔笔记本维修电话 郴州戴尔笔记本维修 戴尔笔记本郴州维修点 华硕笔记本维修点 郴州华硕笔记本维修 郴州笔记本上网维修