Python PyQt5学习之自定义信号

作者:Yunlord 时间:2022-01-06 12:03:52 

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

自定义signal说明:

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

自定义信号的发射,通过emit()方法类实现

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

  1. 定义信号

  2. 定义槽函数

  3. 绑定信号和槽

  4. 发射信号

代码示例

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

样例说明:

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

通过点击F1快捷键,可以显示helpMessage信息。

界面分析:

该界面主要由两个部分组成:一个是打印控制,另一个是操作结果。

通过QHBoxLayout组合起来,如下所示:

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

然后通过creatContorls定义“打印控制”界面,

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)

QSpinBox是一个计数器控件,允许用户选择一个整数值通过单击向上向下或者按键盘上的上下键来增加减少当前显示的值,当然用户也可以输入值。

QComboBox是一个集按钮和下拉选项于一体的控件,也称做下拉列表框。

 然后通过creatResult定义“操作结果”界面:

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

代码分析:

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

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)

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

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

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

Python PyQt5学习之自定义信号

注意事项:

1.自定义的信号在init()函数之前定义

2.自定义型号可以传递,str、int、list、object、float、tuple、dict等很多类型的参数

3.注意signal和slot的调用逻辑,避免signal和slot之间出现死循环。如在slot方法中继续发射该信号

来源:https://blog.csdn.net/kobepaul123/article/details/122972224

标签:Python,PyQt5,自定义,信号
0
投稿

猜你喜欢

  • 保存透明gif时出现锯齿解决法

    2008-06-26 18:10:00
  • 使用Python制作一个数据预处理小工具(多种操作一键完成)

    2023-07-06 20:50:21
  • AJAX实例:根据邮编自动完成地址信息

    2008-03-06 19:44:00
  • Python利用PsUtil实现实时监控系统状态

    2022-11-26 12:43:11
  • Python实现猜数字小游戏

    2022-10-09 18:38:12
  • Python2.7编程中SQLite3基本操作方法示例

    2023-11-14 04:13:32
  • 数据库查询排序使用随机排序结果示例(Oracle/MySQL/MS SQL Server)

    2024-01-18 20:14:13
  • 10分钟快速上手VueRouter4.x教程

    2024-05-02 17:10:38
  • 让长字符自动换行 比如URL和Email地址等

    2008-07-01 14:41:00
  • python处理xml文件操作详解

    2021-11-10 10:31:24
  • python实现微信定时每天和女友发送消息

    2022-08-04 09:43:54
  • 在MySQL中创建实现自增的序列(Sequence)的教程

    2024-01-25 02:42:13
  • .net新兴日志框架Serilog简介

    2023-06-28 16:20:05
  • 讲解设计应用程序时避免阻塞的八个准则

    2009-01-04 14:16:00
  • Python爬虫Scrapy框架CrawlSpider原理及使用案例

    2023-12-23 07:41:55
  • 一文详解Go语言单元测试的原理与使用

    2024-05-09 10:08:03
  • MySQL窗口函数OVER使用示例详细讲解

    2024-01-16 15:56:56
  • 关于numpy中np.nonzero()函数用法的详解

    2023-01-06 12:29:34
  • python 多线程将大文件分开下载后在合并的实例

    2023-05-12 06:27:36
  • Python判断对象是否相等及eq函数的讲解

    2022-04-13 03:15:22
  • asp之家 网络编程 m.aspxhome.com