1. 程式人生 > >PyQt5學習教程11:幾種signal與slot處理事件的方法

PyQt5學習教程11:幾種signal與slot處理事件的方法

    所有的GUI應用程式都是基於事件驅動的,事件不僅可由應用程式產生,諸如Internet連結、窗體管理器,定時器等都可以產生事件。PyQt通過signal和slot處理事件,本文以例項的方式進行講解4種signal與slot處理事件的方法。

1、本文加入LCDNumber和Slider控制元件,通過Slider值的改變來控制LCDNumber的顯示。

2、處理btnOK、btnCancel和btnQuit三個控制元件的clicked事件。

3、從QObject類派生Communicate類,因為每個QObject都可以發射訊號,我們將處理主窗體的mousePressEvent事件,讓其發射訊號,並將其指定到窗體的close slot中。

4、窗體鍵盤按下事件和關閉事件,進行了直接處理。

源程式:

import sys
from PyQt5.QtWidgets import QWidget, \
                              QPushButton, \
                              QToolTip, \
                              QMessageBox, \
                              QApplication, \
                              QDesktopWidget, \
                              QMainWindow, \
                              QAction, \
                              qApp, \
                              QLCDNumber, \
                              QSlider, \
                              QVBoxLayout, \
                              QHBoxLayout
from PyQt5.QtCore import Qt, \
                           QObject, \
                           pyqtSignal
from PyQt5.QtGui import QFont, \
                          QIcon


class Communicate(QObject):
    closeApp = pyqtSignal()


# QMainWindow是QWidget的派生類
class CMainWindow(QMainWindow):

    def __init__(self):
        super().__init__()

        # ToolTip設定
        QToolTip.setFont(QFont('華文楷體', 10))

        # statusBar設定
        self.statusBar().showMessage('準備就緒')

        # 退出Action設定
        exitAction = QAction(QIcon('1.png'), '&Exit', self)
        exitAction.setShortcut('ctrl+Q')
        exitAction.setStatusTip('退出應用程式')
        exitAction.triggered.connect(qApp.quit)     # qApp就相當於QCoreApplication.instance()

        # menuBar設定
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(exitAction)

        # toolBar設定
        self.toolbar = self.addToolBar('Exit')
        self.toolbar.addAction(exitAction)

        # 確認PushButton設定
        btnOK = QPushButton("OK")
        btnOK.setToolTip("點選此按鈕將確認改變!")
        # btnOK.setStatusTip("點選此按鈕將確認改變!")
        btnOK.clicked.connect(self.buttonClicked)
        btnOK.resize(btnOK.sizeHint())

        # 取消PushButton設定
        btnCancel = QPushButton("Cancel")
        btnCancel.setToolTip("點選此按鈕將放棄改變!")
        # btnCancel.setStatusTip("點選此按鈕將放棄改變!")
        btnCancel.clicked.connect(self.buttonClicked)
        btnCancel.resize(btnCancel.sizeHint())

        # 退出PushButton設定
        btnQuit = QPushButton('退出')
        btnQuit.setToolTip("點選此按鈕將退出應用程式!")
        btnQuit.setStatusTip("點選此按鈕將退出應用程式!")
        btnQuit.clicked.connect(qApp.quit)
        btnQuit.resize(btnQuit.sizeHint())

        # PushButton佈局
        hBox = QHBoxLayout()
        hBox.addStretch(1)
        hBox.addWidget(btnOK)
        hBox.addWidget(btnCancel)
        hBox.addWidget(btnQuit)

        # LCDNumber和Slider設定
        lcd = QLCDNumber(self)
        sld = QSlider(Qt.Horizontal, self)
        sld.valueChanged.connect(lcd.display)

        # 佈局
        vBox = QVBoxLayout()
        vBox.addWidget(lcd)
        vBox.addWidget(sld)
        vBox.addLayout(hBox)
        widget = QWidget()
        self.setCentralWidget(widget)  # 建立的widget在窗體的中間位置
        widget.setLayout(vBox)

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

        # Window設定
        self.resize(500, 300)
        self.center()
        self.setFont(QFont('華文楷體', 10))
        self.setWindowTitle('PyQt5應用教程(snmplink編著)')
        self.setWindowIcon(QIcon('10.png'))
        self.show()

    def center(self):
        # 得到主窗體的框架資訊
        qr = self.frameGeometry()
        # 得到桌面的中心
        cp = QDesktopWidget().availableGeometry().center()
        # 框架的中心與桌面中心對齊
        qr.moveCenter(cp)
        # 自身窗體的左上角與框架的左上角對齊
        self.move(qr.topLeft())

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

    def buttonClicked(self):
        sender = self.sender()
        self.statusBar().showMessage(sender.text() + '按下')

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

    def closeEvent(self, QCloseEvent):
        reply = QMessageBox.question(self,
                                     'PyQt5應用教程(snmplink編著)',
                                     "是否要退出應用程式?",
                                     QMessageBox.Yes | QMessageBox.No,
                                     QMessageBox.No)
        if reply == QMessageBox.Yes:
            QCloseEvent.accept()
        else:
            QCloseEvent.ignore()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    MainWindow = CMainWindow()
    sys.exit(app.exec_())

程式解釋:

1、第11行:輸入QLCDNumber模組,用於使用LCDNumber控制元件。

2、第12行:輸入QSlider模組,用於使用Slider控制元件。

3、第16行:輸入QObject模組,用於宣告QObject物件,QObject物件可以發射和接收signal。

4、第17行;輸入pyqtSignal模組,用於發射和接收signal。

5、第22行:定義Communicate類,該類從QObject派生,擁有pyqtSignal型別的成員closeApp。

6、第57行:處理了btnOK的單擊事件,關聯到buttonClicked方法。

7、第64行:處理了btnCancel的單擊事件,關聯到buttonClicked方法。

8、第82行:宣告QLCDNumber物件lcd。

9、第83行:宣告QSlider物件sld。

10、第84行:關聯sld的valueChanged事件的slot為lcd的display方法,這樣當sld的數值改變後,其值將會在lcd上顯示。

11、第95行:建立Communicate物件c。

12、第96行:c的成員closeApp關聯slot為self.close。

13、第116-117行:處理滑鼠點選事件,當滑鼠按下後c的closeApp發射訊號,由於其已於close關聯,所以會觸發窗體關閉。

14、第119-121行,處理OK和Cancel按鈕按下事件,其資訊在狀態列輸出。

15、第123-124行,處理鍵盤按下事件,當發生時,對按鍵進行判斷,如果是ESC鍵,則呼叫sel.close。

程式執行效果:


1、拖動slider時,LCDNumber的值會隨之改變。

2、點選OK和Cancel按鈕,狀態列可以自動區分。

3、點選ESC鍵,可以觸發窗體關閉。

4、滑鼠點選窗體,可以觸發窗體關閉。