PyQt4入门学习笔记(四)

在PyQt4中的事件和信号


事件

所有的GUI应用都是事件驱动的。事件主要是来自于应用的使用者,但是像互联网连接,窗口管理器或者计时器也可以产生事件。当我们调用应用的exec_()方法时,应用就进入了主循环。主循环将抓取事件并且将其发送到对应的对象中去。

在事件模型中,有三个参与者:

  1. 事件源
  2. 事件对象
  3. 事件目标

事件源是改变状态的对象。它生成事件。事件对象囊括了在事件源中状态的改变情况。事件目标是将要通知的对象,事件源通过事件来操控事件对象。

PyQ4有独一无二的信号和槽机制去处理事件。信号和槽被用于在两个对象间进行交流的。。当特定的事件发生时,信号被发出。一个槽可以被任何对象调用。当信号发出并连接到槽时,槽被调用。


新的API

PyQt4.5有一种新式的API用来处理信号和槽。

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

这是旧式的API

下面是新式的API

button.clicked.connect(self.onClicked)

信号和槽

下面是一个使用信号和槽的简单示范例子

#!/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()

运行后如下图
image1

在这个例子中,我们展示了QtGui.QLCDNumberQtGui.QSlider,我们通过滑动小块来改变lcd的值

sld.valueChanged.connect(lcd.display)

在这里我们连接了一个滑块的valueChanged信号到lcddisplay槽。

"sender"是一个发送信号的对象。"receiver"是接受信号的对象。"slot"是对信号起反应的方法。


事件重载管理者(Reimplementing event handler)

在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()方法里我们通过调用senter()方法来确定是哪个按钮被按下了。

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

两个按钮被连接到了相同的槽

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

我们通过调用senter()方法确定了信号源。在这个应用的状态栏,我们显示了是哪个按钮被按下。

如图

image2


产生信号

通过QtCore.QObject创建的对象可以产生信号。在下面的例子里我们将看到如何产生特定的信号

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

"""
ZetCode PyQt4 tutorial 

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

author: Jan Bodnar
website: zetcode.com 
last edited: January 2015
"""

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.QMainWindowclose()槽。

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

当我们点击窗口时,closeApp信号被触发,应用关闭。

在这部分,我们讲了信号和槽。

posted @ 2016-10-20 00:01  唯心不易  阅读(1309)  评论(0编辑  收藏  举报