本文研究的主要是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的定义:
1
2
3
4
5
6
7
8
9
|
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()的使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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、发射信号
通过代码示例来了解一下信号的自定义过程:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
#-*- 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_()) |
运行该函数之后的效果如下:
示例说明:
通过一个模拟打印的界面来详细说明一下关于信号的自定义,在打印的时候可以设定打印的分数,纸张类型,触发“打印”按钮之后,将执行结果显示到右侧;通过全屏预览QCheckBox来选择是否通过全屏模式进行预览,将执行结果显示到右侧。
通过点击F1快捷键,可以显示helpMessage信息。
代码分析:
L12~15:
1
2
3
4
|
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类行的参数。
1
2
3
4
5
6
|
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:
1
2
3
4
5
|
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:
1
2
3
4
5
|
def emitPrintSignal( self ): pList = [] pList.append( self .numberSpinBox.value ()) pList.append( self .styleCombo.currentText()) self .printSignal.emit(pList) |
如代码中所示,在信号发射的时候可以传递python数据类型的参数,在本例中传递list类型的参数pList.
L93~96:
1
2
3
|
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自定义信号实例解析的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
原文链接:http://blog.csdn.net/zhulove86/article/details/52563131