下面我们探索下应用中的事件和信号
一、事件
在GUI编程中,事件是很重要的一部分,事件是由系统或用户产生的,当我们调用应用的 exec_()函数的时候,应用进入主循环,主循环获取事件然后将事件信息传递给对象,Qt具有独特的信号槽机制( signal and slot mechanism)
所有的GUI应用都是事件驱动的,一个应用在其生存过程中对不同的事件类型做出响应,事件主要是由操作应用的用户产生的,但是也可以以其他的任何方式产生,例如:因特网联接,窗口管理器,计时器。在事件模型中,它们都是参与者:
事件源
事件对象
事件目标
信号源是一个对象,而这个对象的状态可以改变。它产生事件,事件源(Event对象)将状态改变封装在内部。事件目标是事件对象想要通知的目标。信号槽机制就是用来在不同的对象之间进行信息交流的。当一个特定的事件发生时,信号被释放,槽 可以是任何python可以调用的东西,当一个释放的信号和一个槽联系起来后,信号一旦释放,该槽酒会被调用
二、信号槽机制
下面是对PySide (Qt)的信号槽机制的一个简单演示
# -*- coding: utf-8 -*-三、重新实现事件处理函数
"""
ZetCode PySide tutorial
In this example, we connect a signal
of a QtGui.QSlider to a slot
of a QtGui.QLCDNumber.
author: Jan Bodnar
website: zetcode.com
last edited: August 2011
"""
import sys
from PySide import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
lcd = QtGui.QLCDNumber(self) # 创建一个LCD表盘
sld = QtGui.QSlider(QtCore.Qt.Horizontal, self) # 创建一个水平滑动轴
vbox = QtGui.QVBoxLayout() # 创建一个竖直框布局类,用于放置lcd,和sld
vbox.addWidget(lcd)
vbox.addWidget(sld)
self.setLayout(vbox)
sld.valueChanged.connect(lcd.display) # 将滑动轴被拖动的事件(信号)和lcd.display函数(槽)联系起来
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
在PySide(Qt)中,事件都是通过重新定义事件处理函数的方式来处理
这里重新定义了keyPressEvent()函数 ,对于每一个窗口都会有一个默认的keyPressEvent()函数继承于QtGui.QWidget,这里重新定义了该函数,使得点击esc键的时候退出当前窗口
四、事件发送者 Event sender
有时候我们可以很方便的知道,哪一个widget是信号的发送者,PySide有一个sender()函数
在本示例中,演示 信号的发出者
import sys5 、释放信号
from PySide import QtGui, QtCore
class Example(QtGui.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
btn1 = QtGui.QPushButton("Button 1", self) # 创建两个按钮以及设置好其位置
btn1.move(30, 50)
btn2 = QtGui.QPushButton("Button 2", self)
btn2.move(150, 50)
btn1.clicked.connect(self.buttonClicked) # 将特定按钮的点击(信号)和 self.buttonClicked(槽)绑定
btn2.clicked.connect(self.buttonClicked)
self.statusBar()
self.setGeometry(300, 300, 290, 150)
self.setWindowTitle('Event sender')
self.show()
def buttonClicked(self): # 定义槽函数
sender = self.sender()
self.statusBar().showMessage(sender.text() + ' was pressed')
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
由QtCore.QObject创建的对象可以释放信号,如果我们点击button,就会产生一个信号(无论你接受与否)在下面的代码中我们会看到,如何释放一个自定义的信号
def mousePressEvent(self, event): # 我们自定义一个信号叫做closeApp只要在窗口内点击鼠标都会释放一个信号
self.c.closeApp.emit()
# -*- coding: utf-8 -*-
"""
ZetCode PySide tutorial
In this example, we show how to emit a
signal.
author: Jan Bodnar
website: zetcode.com
last edited: August 2011
"""
import sys
from PySide import QtGui, QtCore
class Communicate(QtCore.QObject):
closeApp = QtCore.Signal() # 创建一个信号: closeApp
class Example(QtGui.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.c = Communicate() # 基于QtCore.QObject我们创建一个类,当该类实例化的时候创建closeApp信号
self.c.closeApp.connect(self.close) # 将closeApp信号和self.close槽函数联系起来
self.setGeometry(300, 300, 290, 150)
self.setWindowTitle('Emit signal')
self.show()
def mousePressEvent(self, event): # 定义槽函数,当我们在该窗口里点击的时候该信号就会释放
self.c.closeApp.emit()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()