第二章 信号与槽

前言:

信号和槽机制是QT的核心机制,要精通QT编程就必须对信号和槽有所了解。信号和槽是一种高级接口,应用于对象之间的通信,它是QT的核心特性,也是QT区别于其它工具包的重要地方。 

信号和槽是用来在对象间传递数据的方法:当一个特定事件发生的时候,signal会被emit出来,slot调用是用来响应相应的signal的。Qt中对象已经包含了许多预定义的signal(基本组件都有各自特有的预定义的信号),根据使用的场景我们可以添加新的signal。Qt的对象中已经包含了许多预定义的槽函数,但我们也根据使用的场景添加新的槽函数。

信号:

当对象的状态发生改变的时候,信号就由该对象发射 (emit) 出去。当一个信号被发射(emit)时候,与其关联的槽函数被立刻执行。其中该对象只负责发送信号,发射该信号的对象并不知道是那个对象在接收这个信号。这样保证了对象与对象之间的低耦合。 如果存在信号和多个槽函数相关联的时候,当信号被发射时,这些槽的执行顺序将会是随机的、不确定的。

槽:

用于接受信号,而且槽只是普通的对象成员函数。当和槽连接的信号被发射时,槽会被调用。一个槽并不知道是否有任何信号与自己相连接。

下面通过几个例子介绍信号与槽函数的使用

2.1  一个信号连接一个槽

很多程序上是有“开始”按钮的,按下去后按钮上的文本就变成了“停止”。下面就是一个示例(之后的代码都会用类来呈现):

 1 import sys
 2 from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
 3 
 4 
 5 class Demo(QWidget):                                                # 1
 6     def __init__(self): 
 7         super(Demo, self).__init__()
 8         self.button = QPushButton("开始", self)               # 2
 9         self.button.clicked.connect(self.change_text)       # 3
10 
11     def change_text(self):
12         self.button.setText("结束")                                     # 4      
13         self.button.clicked.disconnect(self.change_text)      # 5
14 
15 
16 if __name__ == '__main__':
17     app = QApplication(sys.argv)
18     demo = Demo()                                                     # 6
19     demo.show()                                                         # 7
20     sys.exit(app.exec_())
View Code

#1. 该类继承QWidget,可以将QWidget看作是一种毛坯房,还没有装修,而我们往其中放入QPushButton、QLabel等控件就相当于在装修这间毛坯房。类似功能还有QMainWindow和QDialog,之后章节再讲述;

#2. 实例化一个QPushButton,因为继承于QWidget,所以self不能忘了(相当于告诉程序这个QPushButton是放在QWidget这个房子中的);

#3. 连接信号与槽函数。self.button就是一个控件,clicked(按钮被点击)是该控件的一个信号,connect()即连接,self.change_text即下方定义的函数(我们称之为槽函数)。所以通用的公式可以是:widget.signal.connect(slot);

#4. 将按钮文本从‘开始’改成‘结束’;

#5. 信号和槽解绑,解绑后再按按钮你会发现控制台不会再输出‘change text’,如果把这行解绑的代码注释掉,你会发现每按一次按钮,控制台都会输出一次‘change text’;

#6. 实例化Demo类;

#7. 使demo可见,其中的控件自然都可见(除非某控件刚开始设定隐藏)

现在用鸣枪和开跑来分析下上面这个例子:按钮控件是裁判,他鸣枪发出信号(clicked),change_text()槽函数运行就是选手开跑。
运行结果:

 

 点击“开始”后文本变为:

 

 2.2  多个信号连接同一个槽

在2.1中一个信号连接一个槽函数,现在研究多个信号连接同一个槽函数

 

QPushButton还有两个信号是pressed和released,这两个信号解释如下:

 

pressed: 当鼠标在button上并点击左键的时候,触发信号 。
released: 当鼠标左键被释放的时候触发信号。
所以其实pressed和released两个连起来就是一个完整的clicked。

 1 import sys
 2 from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
 3 
 4 
 5 class Demo(QWidget):                                         
 6     def __init__(self):
 7         super(Demo, self).__init__()
 8         self.button = QPushButton("开始", self)             
 9         self.button.pressed.connect(self.change_text)       # 1
10         self.button.released.connect(self.change_text)      # 2
11 
12     def change_text(self):
13         if self.button.text() == "开始":                             # 3
14             self.button.setText("结束")
15         else:
16             self.button.setText("开始")
17 
18 
19 if __name__ == '__main__':
20     app = QApplication(sys.argv)
21     demo = Demo()                                           
22     demo.show()                                             
23     sys.exit(app.exec_())
View Code

#1-#2. 将pressed和released信号连接搭配change_text()槽函数上;

#3. 若当前按钮文本为‘开始t’,则将文本改为‘开始’;若为‘结束’,则改为‘结束’。

所以当鼠标点击按钮不放时,发出pressed信号,调用槽函数,将‘开始’文本改为‘结束’;当鼠标放开后释放released信号,再次调用槽函数,将文本改回‘开始’。
运行程序:

 

 点击“开始”释放后:

 

2.3  一个信号与另一个信号连接

 1 import sys
 2 from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
 3 
 4 
 5 class Demo(QWidget):
 6     def __init__(self):
 7         super(Demo, self).__init__()
 8         self.button = QPushButton("开始", self)
 9         self.button.pressed.connect(self.button.released)       # 1
10         self.button.released.connect(self.change_text)          # 2
11 
12     def change_text(self):
13         if self.button.text() == "开始":                                 # 3
14             self.button.setText("结束")
15         else:
16             self.button.setText("开始")
17 
18 
19 if __name__ == '__main__':
20     app = QApplication(sys.argv)
21     demo = Demo()
22     demo.show()
23     sys.exit(app.exec_())
View Code

#1- #2. 将pressed信号和released信号连接起来,而released信号则与槽函数连接。这样当点击不放时,pressed信号发出,released信号也会发出,从而启动槽函数。释放鼠标则发出released信号,再次启动槽函数。所以程序运行效果跟2.2小节其实是一样的。
2.4  一个信号连接多个槽函数

信号都为clicked,连接多个槽函数

 1 # _*_ coding:utf-8 _*_
 2 import sys
 3 from PyQt5.QtWidgets import QApplication, QWidget,QPushButton
 4 
 5 
 6 class Demo(QWidget):
 7     def __init__(self):
 8         super(Demo, self).__init__()
 9         self.resize(300, 300)                  # 将窗口大小设置为300*300
10         self.setWindowTitle("demo")            # 将窗口名字设置为“demo”
11         self.button = QPushButton('start', self)
12         self.button.clicked.connect(self.change_text)
13         self.button.clicked.connect(self.change_window_size)   # 信号clicked连接多个槽函数
14         self.button.clicked.connect(self.change_window_title)
15 
16     def change_text(self):                             # 改变文本内容
17         self.button.setText("stop")
18         self.button.clicked.disconnect(self.change_text)
19 
20     def change_window_size(self):            # 改变窗口大小
21         self.resize(500, 500)
22         self.button.clicked.disconnect(self.change_window_size)
23 
24     def change_window_title(self):            # 改变窗口名称
25         self.setWindowTitle("槽函数示例")
26         self.button.clicked.disconnect(self.change_window_title)
27 
28 
29 if __name__ == '__main__':
30     app = QApplication(sys.argv)
31     demo = Demo()
32     demo.show()
33     sys.exit(app.exec_())
View Code

2.5 自定义信号

 

posted @ 2019-09-30 17:25  nclong  阅读(252)  评论(0)    收藏  举报