[PyQt]如何使用信号槽?

[PyQt]如何使用信号槽? - codeio - 博客园

[PyQt]如何使用信号槽?

前言

信号(singal)与槽(slot)用于对象相互通信,信号:当某个对象的某个事件发生时,触发一个信号,槽:响应指定信号的所做的反应,其实信号槽类似于.NET里面的委托、事件,比如Repeater控件类,当行数据绑定后,触发一个ItemDataBound事件,不管使用者使用会监听该事件并做额外处理,其控件类内部都会触发该事件,这种机制很多程度提高了类的封装性和完整性。

PyQt的窗体控件类已经有很多的内置信号,开发者也可以添加自己的自定义信号,信号槽有如下特点:

- 一个信号可以连接到许多插槽
- 一个信号也可以连接到另一个信号
- 信号参数可以是任何Python类型
- 一个插槽可以连接到许多信号
- 连接可能会直接(同步)或排队(即异步
- 连接可能会跨线程
- 信号可能会断开

(以上几条特点翻译于官方文档),接下来,我将以若干个实例,来体现以上几个特点。

内置信号槽、自定义信号槽的使用

内置信号槽的使用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from PyQt4.QtGui import *
from PyQt4.QtCore import *
 
def sinTest():
     btn.setText( "按钮文本改变" )
 
app = QApplication([])
 
main = QWidget()
main.resize( 200 , 100 )
btn = QPushButton( "按钮文本" ,main)
##按钮btn的内置信号连接名为sinTest的槽
btn.clicked.connect(sinTest)
main.show()
 
app.exec_()

 

运行结果:

[PyQt]如何使用信号槽?

 

自定义信号槽的使用

?
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
from PyQt4.QtGui import *
from PyQt4.QtCore import *
 
class SinClass(QObject):
     
     ##声明一个无参数的信号
     sin1 = pyqtSignal()
     
     ##声明带一个int类型参数的信号
     sin2 = pyqtSignal( int )
     
     ##声明带一个int和str类型参数的信号
     sin3 = pyqtSignal( int , str )
 
     ##声明带一个列表类型参数的信号
     sin4 = pyqtSignal( list )
 
     ##声明带一个字典类型参数的信号
     sin5 = pyqtSignal( dict )
 
     ##声明一个多重载版本的信号,包括了一个带int和str类型参数的信号,以及带str参数的信号
     sin6 = pyqtSignal([ int , str ], [ str ])
     
     def __init__( self ,parent = None ):
         super (SinClass, self ).__init__(parent)
 
         ##信号连接到指定槽
         self .sin1.connect( self .sin1Call)
         self .sin2.connect( self .sin2Call)
         self .sin3.connect( self .sin3Call)
         self .sin4.connect( self .sin4Call)
         self .sin5.connect( self .sin5Call)
         self .sin6[ int , str ].connect( self .sin6Call)
         self .sin6[ str ].connect( self .sin6OverLoad)
 
         ##信号发射
         self .sin1.emit()
         self .sin2.emit( 1 )
         self .sin3.emit( 1 , "text" )
         self .sin4.emit([ 1 , 2 , 3 , 4 ])
         self .sin5.emit({ "name" : "codeio" , "age" : "25" })
         self .sin6[ int , str ].emit( 1 , "text" )
         self .sin6[ str ].emit( "text" )
         
     def sin1Call( self ):
         print ( "sin1 emit" )
 
     def sin2Call( self ,val):
         print ( "sin2 emit,value:" ,val)
 
     def sin3Call( self ,val,text):
         print ( "sin3 emit,value:" ,val,text)
 
     def sin4Call( self ,val):
         print ( "sin4 emit,value:" ,val)
         
     def sin5Call( self ,val):
         print ( "sin5 emit,value:" ,val)
 
     def sin6Call( self ,val,text):
         print ( "sin6 emit,value:" ,val,text)
 
     def sin6OverLoad( self ,val):
         print ( "sin6 overload emit,value:" ,val)
 
sin = SinClass()

 

运行结果:
sin1 emit
sin2 emit,value: 1
sin3 emit,value: 1 text
sin4 emit,value: [1, 2, 3, 4]
sin5 emit,value: {'age': '25', 'name': 'codeio'}
sin6 emit,value: 1 text
sin6 overload emit,value: text

 

信号槽N对N连接、断开连接以及多线程信号槽通信

信号槽N对N连接、断开连接

?
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
from PyQt4.QtGui import *
from PyQt4.QtCore import *
 
class SinClass(QObject):
     
     ##声明一个无参数的信号
     sin1 = pyqtSignal()
     
     ##声明带一个int类型参数的信号
     sin2 = pyqtSignal( int )
     
     def __init__( self ,parent = None ):
         super (SinClass, self ).__init__(parent)
 
         ##信号sin1连接到sin1Call和sin2Call这两个槽
         self .sin1.connect( self .sin1Call)
         self .sin1.connect( self .sin2Call)
         
         ##信号sin2连接到信号sin1
         self .sin2.connect( self .sin1)
 
         ##信号发射
         self .sin1.emit()
         self .sin2.emit( 1 )
 
         ##断开sin1、sin2信号与各槽的连接
         self .sin1.disconnect( self .sin1Call)
         self .sin1.disconnect( self .sin2Call)
         self .sin2.disconnect( self .sin1)
 
         ##信号sin1和sin2连接同一个槽sin1Call
         self .sin1.connect( self .sin1Call)
         self .sin2.connect( self .sin1Call)
 
         ##信号再次发射
         self .sin1.emit()
         self .sin2.emit( 1 )
         
     def sin1Call( self ):
         print ( "sin1 emit" )
 
     def sin2Call( self ):
         print ( "sin2 emit" )
 
sin = SinClass()

 

运行结果:
sin1 emit
sin2 emit
sin1 emit
sin2 emit
sin1 emit
sin1 emit

 

多线程信号槽通信

?
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
from PyQt4.QtCore import *
from PyQt4.QtGui import *
 
class Main(QWidget):
     def __init__( self , parent = None ):
         super (Main, self ).__init__(parent)
 
         ##创建一个线程实例并设置名称、变量、信号槽
         self .thread = MyThread()
         self .thread.setIdentity( "thread1" )
         self .thread.sinOut.connect( self .outText)
         self .thread.setVal( 6 )
         
     def outText( self ,text):
         print (text)
         
class MyThread(QThread):
     
     sinOut = pyqtSignal( str )
     
     def __init__( self ,parent = None ):
         super (MyThread, self ).__init__(parent)
 
         self .identity = None
 
     def setIdentity( self ,text):
         self .identity = text
         
     def setVal( self ,val):
         self .times = int (val)
 
         ##执行线程的run方法
         self .start()
         
     def run( self ):
         while self .times > 0 and self .identity:
             ##发射信号
             self .sinOut.emit( self .identity + " " + str ( self .times))
             self .times - = 1
 
app = QApplication([])
 
main = Main()
main.show()
 
app.exec_()

 

运行结果:
thread1 6
thread1 5
thread1 4
thread1 3
thread1 2
thread1 1

 

小结

该篇主要介绍了信号槽多对多连接、连接断开、多线程如何使用信号槽进行通信,Qt除了窗体部件类,还提供了很多其他系统相关操作类,使用起来很方便,多线程使用了Qt自带的QThread类,这里只是做了个简单的测试,多线程还有许多要深入探究的,有几个心得:

- 对于单一信号连接多个槽的情况,发射信号后,槽的执行顺序就是信号槽连接的顺序

- GUI所在的线程是主线程,线程之间可以通过信号槽来通信,这个方法适用于重写PyQt部件类后对外开发接口

- 我使用的环境是:PyQt4.8.4,Qt4.7.2,Python3.2,这个版本的PyQt将使用新的信号槽风格

- 槽的参数个数可以小于等于信号的参数个数, 换句话说,信号并不关心谁使用了它,怎么使用它,槽可以选择性地使用信号的参数

- 用pyqtSignal来声明一个新信号,它的参数可能是Python的类型对象或者C++的类型

- 新的信号只能在QObject的子类中声明

你可能感兴趣的:(qt)