事件与信号
事件 Event
所有的GUI程序都是事件驱动的。事件主要由用户触发,但也可能有其他触发方式:例如网络连接、window manager或定时器。当我们调用QApplication的exec_()方法时会使程序进入主循环。主循环会获取并分发事件。
在事件模型中,有三个参与者:
- 事件源
- 事件对象
- 事件接收者
事件源是状态发生变化的对象。它会生成事件。事件(对象)封装了事件源中状态的变动。事件接收者是要通知的对象。事件源对象将事件处理的工作交给事件接收者。
PyQt5有一个独特的signal&slot(信号槽)机制来处理事件。信号槽用于对象间的通信。signal在某一特定事件发生时被触发,slot可以是任何callable对象。当signal触发时会调用与之相连的slot。
import sys from PyQt5.QtCore import Qt from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider, QVBoxLayout, QApplication) class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): lcd = QLCDNumber(self) #创建LCD数字对象 sld = QSlider(Qt.Horizontal, self) #创建滑块水平拉动 vbox = QVBoxLayout() #垂直布局管理器 vbox.addWidget(lcd) #为lcd和sld布局,因为垂直所以一上一下 vbox.addWidget(sld) self.setLayout(vbox) sld.valueChanged.connect(lcd.display) #这个例子中展示了一个QtGui.QLCDNumber和QtGui.QSlider。 # lcd的值会随着滑块的拖动而改变。 #在这里我们将滚动条的valueChanged信号连接到lcd的display插槽。 #sender是发出信号的对象。receiver是接收信号的对象。slot(插槽)是对信号做出反应的方法。 self.setGeometry(300, 300, 250, 150) self.setWindowTitle('Signal & slot') self.show() if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() sys.exit(app.exec_())
按键触发事件
设置按键触发,需要要到QWidget下的keyPressEvent方法,不过我们可自定制
import sys from PyQt5.Qt import Qt from PyQt5.QtWidgets import QApplication,QWidget class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowTitle("biao") self.setGeometry(300,300,300,300) self.show() def keyPressEvent(self, QKeyEvent): #自定义按键触发事件 if QKeyEvent.key() == Qt.Key_Escape: #当按键为Exs时 self.close() if __name__ == '__main__': app =QApplication(sys.argv) ex = Example() sys.exit(app.exec_())
事件发送者
有时需要知道信号是由哪个控件发出的。对此PyQt5提供了sender()方法。
1 from PyQt5.QtWidgets import QMainWindow,QApplication,QPushButton 2 import sys 3 4 class Example(QMainWindow): 5 6 def __init__(self): 7 super().__init__() 8 9 self.initUI() 10 11 def initUI(self): 12 13 btn1 = QPushButton("按钮1",self) 14 btn1.move(30,30) 15 btn2 = QPushButton("按钮2",self) 16 btn2.move(130,30) 17 18 btn1.clicked.connect(self.buttonCliked) #创立事件,当btn被点击时 19 btn2.clicked.connect(self.buttonCliked) 20 self.statusBar() #用QMainWindow才能有状态栏,菜单栏,工具栏 21 22 self.setGeometry(300,300,300,300) 23 self.setWindowTitle("biaobiao") 24 self.show() 25 26 def buttonCliked(self): 27 #通过调用sender()方法来判断信号源, 并将其名称显示在窗体的状态栏中。 28 sender = self.sender() #获取sender对象 29 self.statusBar().showMessage(sender.text()+'was pressed') #获取信号源名称 30 31 if __name__ == '__main__': 32 33 app = QApplication(sys.argv) 34 ex = Example() 35 sys.exit(app.exec_())
发出信号
通过QObject创建的对象可以发出信号
信号要与事件连接,事件由事件管理器处理器控制
import sys from PyQt5.QtWidgets import QMainWindow,QApplication from PyQt5.QtCore import QObject,pyqtSignal class Communicate(QObject): #创建连接 closeAPP =pyqtSignal() #创建信号 class Exmple(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self.c = Communicate() #创建连接 self.c.closeAPP.connect(self.close) #信号连接事件 self.setWindowTitle("biaobiao") self.setGeometry(300,300,300,300) self.show() def mousePressEvent(self, event): #事件处理器 self.c.closeAPP.emit() if __name__ == '__main__': app =QApplication(sys.argv) ex = Exmple() sys.exit(app.exec_())