全部的GUI應用都是事件驅動的。事件主要是來自於應用的使用者,可是像互聯網鏈接,窗口管理器或者計時器也能夠產生事件。當咱們調用應用的exec_()
方法時,應用就進入了主循環。主循環將抓取事件而且將其發送到對應的對象中去。python
在事件模型中,有三個參與者:web
事件源是改變狀態的對象。它生成事件。事件對象囊括了在事件源中狀態的改變狀況。事件目標是將要通知的對象,事件源經過事件來操控事件對象。api
PyQ4有獨一無二的信號和槽機制去處理事件。信號和槽被用於在兩個對象間進行交流的。。當特定的事件發生時,信號被髮出。一個槽能夠被任何對象調用。當信號發出並鏈接到槽時,槽被調用。app
PyQt4.5有一種新式的API用來處理信號和槽。ide
QtCore.QObject.connect(button, QtCore.SIGNAL('clicked()'), self.onClicked)
這是舊式的APIui
下面是新式的APIthis
button.clicked.connect(self.onClicked)
下面是一個使用信號和槽的簡單示範例子code
#!/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()
運行後以下圖
對象
在這個例子中,咱們展現了QtGui.QLCDNumber
和QtGui.QSlider
,咱們經過滑動小塊來改變lcd的值blog
sld.valueChanged.connect(lcd.display)
在這裏咱們鏈接了一個滑塊的valueChanged
信號到lcd
的display
槽。
"sender"是一個發送信號的對象。"receiver"是接受信號的對象。"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()
方法裏咱們經過調用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()
方法肯定了信號源。在這個應用的狀態欄,咱們顯示了是哪一個按鈕被按下。
如圖
經過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.QMainWindow
的close()
槽。
class Communicate(QtCore.QObject): closeApp = QtCore.pyqtSignal()
當咱們點擊窗口時,closeApp
信號被觸發,應用關閉。
在這部分,咱們講了信號和槽。