分享

PyQt4 教程(5)

 学海无涯GL 2014-10-24

PyQt4 中的事件与信号

在这一节中,将会接触到程序中事件和信号的 we will explore events and singnals occuring in applications.

事件

事件是gui程序中最重要的部分。事件是由用或系统发出的。当我们调用程序的exec_()方法,程序进入了主循环。主循环获取事件并负责将其传送到对象。 Trolltech通过其独特的信号与槽的机制来进行掌控。

事件是gui程序的最重要部分。所有的gui程序是事件驱动的。程序在运行期间,处理各种事件,主要处理由用户激发的程序,但也可以由网络链接,窗口管理器,计时器。在事件模型,有三个组成部分:


  • 事件源(event source)
  • 事件对象(event object)
  • 事件目标(event target)

事件源 是发生状态改变改变的对象。它产生事件。事件对象将事件源状态变化封装起来。事件目标是需要告知的对象。事件源对象将事件传送给事件目标处理。

当我们调用exec_() 方法,程序进入了主循环。主循环获取事件并将它们发送给对象。信号和槽用来对象间的通信。当一个事件发生时,信号 就生成了。slot 可以是任何python可调用的函数。信号所连接的槽的调用,是在信号生成后。

新 API

PyQt4.5 引入信号与槽的一种新的API 风格。

QtCore.QObject.connect(button, QtCore.SIGNAL('clicked()'), self.onClicked)

上边是老式的API

button.clicked.connect(self.onClicked)

这是新式的更符合python标准。

信号&槽

这是一个展示PyQt4中的信号与槽。

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
ZetCode PyQt4 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: October 2011
"""

import sys
from PyQt4 import QtGui, QtCore


class Example(QtGui.QWidget):
    
    def __init__(self):
        super(Example, self).__init__()
        
        self.initUI()
        
    def initUI(self):
        
        lcd = QtGui.QLCDNumber(self)
        sld = QtGui.QSlider(QtCore.Qt.Horizontal, self)

        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(lcd)
        vbox.addWidget(sld)

        self.setLayout(vbox)
        sld.valueChanged.connect(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()

In our example, we display a QtGui.QLCDNumber and a QtGui.QSlider. We change the lcd number by dragging the slider knob.

sld.valueChanged.connect(lcd.display)

Here we connect a valueChanged signal of the slider to the display slot of the lcd number.

The sender is an object that sends a signal. The receiver is the object, that receives the signal. The slot is the method, that reacts to the signal.


Signals & slot
Figure: Signal & slot

重载事件处理器

PyQt4 事件处理通常要重载事件处理器。

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
ZetCode PyQt4 tutorial 

In this example, we reimplement an 
event handler. 

author: Jan Bodnar
website: zetcode.com 
last edited: October 2011
"""

import sys
from PyQt4 import QtGui, QtCore


class Example(QtGui.QWidget):
    
    def __init__(self):
        super(Example, self).__init__()
        
        self.initUI()
        
    def initUI(self):      
        
        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Event handler')
        self.show()
        
    def keyPressEvent(self, e):
        
        if e.key() == QtCore.Qt.Key_Escape:
            self.close()
        
def main():
    
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

在我们的例子里, 我们重载了 keyPressEvent() 事件处理器。

def keyPressEvent(self, e):
    
    if e.key() == QtCore.Qt.Key_Escape:
        self.close()

如果按了esc键,程序结束。

事件发送者

有时候需要知道信号的发送者,为了方便使用PyQt4 有一个 sender() 方法。

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
ZetCode PyQt4 tutorial 

In this example, we determine the event sender
object.

author: Jan Bodnar
website: zetcode.com 
last edited: October 2011
"""

import sys
from PyQt4 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)            
        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()

在我们例子里有两个按钮。在 buttonClicked()方法里我们判断哪个按钮被按下使用了sender()

btn1.clicked.connect(self.buttonClicked)            
btn2.clicked.connect(self.buttonClicked)

两个按钮都被连接到了相同的槽函数。

def buttonClicked(self):
  
    sender = self.sender()
    self.statusBar().showMessage(sender.text() + ' was pressed')

我们使用sender()方法判断信号的发出者。在程序的状态栏里显示哪里个按钮被按下。


Event sender
Figure: Event sender

发出信号

从QtCore.QObject 中创建出来的类都能发出信号。如果我们点击按钮,一个 clicked() 信号生成。在下边例子里我们如何生成一个信号。

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
ZetCode PyQt4 tutorial 

In this example, we show how to emit a
custom signal. 

author: Jan Bodnar
website: zetcode.com 
last edited: October 2011
"""

import sys
from PyQt4 import QtGui, QtCore


class Communicate(QtCore.QObject):
    
    closeApp = QtCore.pyqtSignal() 
    

class Example(QtGui.QMainWindow):
    
    def __init__(self):
        super(Example, self).__init__()
        
        self.initUI()
        
    def initUI(self):      

        self.c = Communicate()
        self.c.closeApp.connect(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()

我们创建了一个名叫closeApp的信号。当鼠标按下时,信号发出。信号被连接到QtGui.QMainWindow的close()槽函数里

class Communicate(QtCore.QObject):
    
    closeApp = QtCore.pyqtSignal() 

创建了一个QtCore.QObject的子类。 当其初始化时,创建一个名叫closeApp的信号。

self.c = Communicate()
self.c.closeApp.connect(self.close)     

一个Communicate类的实例被创建。我们把closeApp的信号连接到QtGui.QMainWindow的close()槽函数。

def mousePressEvent(self, event):
    
    self.c.closeApp.emit()

当在窗口上点击鼠票时, closeApp 信号发出。

    

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多