PyQt5(4)——控件事件响应与信号槽

事件(Events)是 GUI 程序中很重要的一部分,它由用户操作或系统产生。当我们调用程序的 exec_()方法时,程序就会进入主循环中。主循环捕获事件并将它们发送给相应的对象进行处理。

为此,Qt引入了一种独一无二的处理模式:信号与槽机制。信号和槽可以说是 Qt 的精髓所在。

信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性,也是 QT 区别于其它工具包的重要地方。它为高层次的事件处理自动生成所需要的附加代码。在我们所熟知的很多 GUI 工具包中,窗口小部件 (widget) 都有一个回调函数用于响应它们能触发的每个动作,这个回调函数通常是一个指向某个函数的指针。但是,在 QT 中信号和槽取代了这些凌乱的函数指针,使得我们编写这些通信程序更为简洁明了。

所有从 QObject 或其子类 ( 例如 Qwidget) 派生的类都能够包含信号和槽。当对象改变其状态时,信号就由该对象发射 (emit) 出去,这就是对象所要做的全部事情,它不知道另一端是谁在接收这个信号。这就是真正的信息封装,它确保对象被当作一个真正的软件组件来使用。槽用于接收信号,但它们是普通的对象成员函数。一个槽并不知道是否有任何信号与自己相连接。而且,对象并不了解具体的通信机制。你可以将很多信号与单个的槽进行连接,也可以将单个的信号与很多的槽进行连接,甚至于将一个信号与另外一个信号相连接也是可能的,这时无论第一个信号什么时候发射系统都将立刻发射第二个信号。

简而言之:

信号(singal)与槽(slot)用于对象相互通信。

信号:当某个对象的某个事件发生时,触发一个信号

槽:响应指定信号的所做的反应


信号与槽构造了一个强大的部件编程机制,这种机制很多程度提高了类的封装性和完整性。

  PyQt的窗体控件类已经有很多的内置信号,开发者也可以添加自己的自定义信号,信号槽有如下特点:

    - 一个信号可以连接到许多插槽。
    - 一个信号也可以连接到另一个信号。
    - 信号参数可以是任何Python类型。
    - 一个插槽可以连接到许多信号。
    - 连接可能会直接(即同步)或排队(即异步)。
    - 连接可能会跨线程。
    - 信号可能会断开


我们可以使用Qt Designer编辑界面的同时,编辑其信号槽处理。


简单示例,给一个QMainWindow窗体添加了一个PushButton按钮,当用户点击按钮时,关闭窗口。

下图中,我们先点击上方工具栏中“编辑信号/槽”按钮,将编辑器切换进入信号/槽编辑状态。

然后,将提前添加好的BtnClose按钮做拖动到主窗体的操作,这时候会弹出一个“配置连接”窗口。

左边列表中是按钮对应事件的信号,右边是窗体MainWindow可以被绑定的槽。

我们选择BtnClose的Clicked信号绑定到窗体的Close槽。


PyQt5(4)——控件事件响应与信号槽_第1张图片


然后保存配置文件,执行使用pyuic5.bat进行ui到py转换的批处理。

得到如下代码

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'TestFrm.ui'
#
# Created by: PyQt5 UI code generator 5.5.1
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(701, 441)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.BtnClose = QtWidgets.QPushButton(self.centralwidget)
        self.BtnClose.setGeometry(QtCore.QRect(450, 350, 75, 23))
        self.BtnClose.setObjectName("BtnClose")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 701, 23))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.BtnClose.clicked.connect(MainWindow.close)#将BtnClose的clicked信号和MainWindow的close槽连接
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.BtnClose.setText(_translate("MainWindow", "Close"))

这时候我们再添加对应的UI和界面类绑定及运行的代码

if __name__=="__main__":    
    import sys    
    app=QtWidgets.QApplication(sys.argv)    
    formObj=QtWidgets.QMainWindow()  #注意,这里和我们一开始创建窗体时使用的界面类型相同  
    ui=Ui_MainWindow()    
    ui.setupUi(formObj)    
    formObj.show()    
    sys.exit(app.exec_())  

运行代码,我们发现已经可以点击Close按钮将窗口关闭了




我们也可以自行定义响应函数,下面我们将原来BtnClose按钮绑定的槽换成我们自己编写的成员函数

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'TestFrm.ui'
#
# Created by: PyQt5 UI code generator 5.5.1
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(701, 441)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.BtnClose = QtWidgets.QPushButton(self.centralwidget)
        self.BtnClose.setGeometry(QtCore.QRect(450, 350, 75, 23))
        self.BtnClose.setObjectName("BtnClose")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 701, 23))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        #self.BtnClose.clicked.connect(MainWindow.close)#将BtnClose的clicked信号和MainWindow的close槽连接
        self.BtnClose.clicked.connect(self.clickTime)#换成绑定自己编写的函数   <-----------
        self.clickCnt = 0#记录点击次数                                         <-----------
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.BtnClose.setText(_translate("MainWindow", "Close"))

    #当点击按钮时触发,修改按钮名                                              <-----------
    def clickTime(self):
        self.clickCnt+=1#点击次数递增
        _translate = QtCore.QCoreApplication.translate
        self.BtnClose.setText(_translate("MainWindow", "点击次数 %d"%self.clickCnt))#将按钮名改成点击次数
        

if __name__=="__main__":    
    import sys    
    app=QtWidgets.QApplication(sys.argv)    
    formObj=QtWidgets.QMainWindow()  #注意,这里和我们一开始创建窗体时使用的界面类型相同  
    ui=Ui_MainWindow()    
    ui.setupUi(formObj)    
    formObj.show()    
    sys.exit(app.exec_())  


运行代码,实现效果如下,每次点击按钮,按钮的文字内容就会修改成点击的次数

PyQt5(4)——控件事件响应与信号槽_第2张图片

你可能感兴趣的:(Python,PyQt)