Python Qt GUI设计入门信号与槽函数

Posted 肆拾伍

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python Qt GUI设计入门信号与槽函数相关的知识,希望对你有一定的参考价值。


前言

在上一章我们已经讲解了如何使用Qt生成的py文件模板,但是这还仅仅只能实现图形界面部分,对于整个GUI的逻辑处理和函数响应都没有涉及,这里就和MATLAB中每个控件的callback和其他响应函数一样。Qt的函数响应分为信号和槽函数,信号就是用户的动作,槽函数就是相应的响应。


一、内置信号和槽函数

1.新建项目

我们首先来创建一个项目,与之前不一样,这里我们需要还要创建相应的c++文件,并不需要我们编辑,只是用于查看一些信息。
在这里插入图片描述
一路选下去。
在这里插入图片描述
在这里插入图片描述
打开新建的ui文件:
在这里插入图片描述
设计好界面:
在这里插入图片描述

2.信号与槽函数的关联

在这里插入图片描述
左键长按 确认pushbutton拖动到界面外:
在这里插入图片描述
在这里插入图片描述
这里是使点击确认按键关闭dialog窗口,下面还是使用pyuic5 -o Proj2_dialog.py dialog.ui 生成py文件,文件名需要改成自己的,打开py文件:

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

# Form implementation generated from reading ui file 'dialog.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(342, 240)
        self.plainTextEdit = QtWidgets.QPlainTextEdit(Dialog)
        self.plainTextEdit.setGeometry(QtCore.QRect(9, 59, 281, 138))
        font = QtGui.QFont()
        font.setPointSize(20)
        font.setBold(True)
        font.setWeight(75)
        self.plainTextEdit.setFont(font)
        self.plainTextEdit.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
        self.plainTextEdit.setCenterOnScroll(False)
        self.plainTextEdit.setObjectName("plainTextEdit")
        self.horizontalLayoutWidget = QtWidgets.QWidget(Dialog)
        self.horizontalLayoutWidget.setGeometry(QtCore.QRect(80, 30, 240, 21))
        self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.radioButton_3 = QtWidgets.QRadioButton(self.horizontalLayoutWidget)
        self.radioButton_3.setObjectName("radioButton_3")
        self.horizontalLayout.addWidget(self.radioButton_3)
        self.radioButton_2 = QtWidgets.QRadioButton(self.horizontalLayoutWidget)
        self.radioButton_2.setObjectName("radioButton_2")
        self.horizontalLayout.addWidget(self.radioButton_2)
        self.radioButton = QtWidgets.QRadioButton(self.horizontalLayoutWidget)
        self.radioButton.setObjectName("radioButton")
        self.horizontalLayout.addWidget(self.radioButton)
        self.horizontalLayoutWidget_3 = QtWidgets.QWidget(Dialog)
        self.horizontalLayoutWidget_3.setGeometry(QtCore.QRect(9, 203, 311, 30))
        self.horizontalLayoutWidget_3.setObjectName("horizontalLayoutWidget_3")
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_3)
        self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_3.setSpacing(30)
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        self.pushButton_3 = QtWidgets.QPushButton(self.horizontalLayoutWidget_3)
        self.pushButton_3.setObjectName("pushButton_3")
        self.horizontalLayout_3.addWidget(self.pushButton_3)
        self.pushButton_2 = QtWidgets.QPushButton(self.horizontalLayoutWidget_3)
        self.pushButton_2.setObjectName("pushButton_2")
        self.horizontalLayout_3.addWidget(self.pushButton_2)
        self.pushButton = QtWidgets.QPushButton(self.horizontalLayoutWidget_3)
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout_3.addWidget(self.pushButton)
        self.label = QtWidgets.QLabel(Dialog)
        self.label.setGeometry(QtCore.QRect(20, 10, 54, 20))
        self.label.setObjectName("label")
        self.horizontalLayoutWidget_2 = QtWidgets.QWidget(Dialog)
        self.horizontalLayoutWidget_2.setGeometry(QtCore.QRect(80, 10, 240, 21))
        self.horizontalLayoutWidget_2.setObjectName("horizontalLayoutWidget_2")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_2)
        self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.checkBox_3 = QtWidgets.QCheckBox(self.horizontalLayoutWidget_2)
        self.checkBox_3.setObjectName("checkBox_3")
        self.horizontalLayout_2.addWidget(self.checkBox_3)
        self.checkBox_2 = QtWidgets.QCheckBox(self.horizontalLayoutWidget_2)
        self.checkBox_2.setObjectName("checkBox_2")
        self.horizontalLayout_2.addWidget(self.checkBox_2)
        self.checkBox = QtWidgets.QCheckBox(self.horizontalLayoutWidget_2)
        self.checkBox.setObjectName("checkBox")
        self.horizontalLayout_2.addWidget(self.checkBox)
        self.label_2 = QtWidgets.QLabel(Dialog)
        self.label_2.setGeometry(QtCore.QRect(20, 30, 54, 16))
        self.label_2.setObjectName("label_2")
# 槽函数的关联在此处
        self.retranslateUi(Dialog)
        self.pushButton_2.clicked.connect(Dialog.accept) # 这里是确认
        self.pushButton.clicked.connect(Dialog.close)   # 这里是取消
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.plainTextEdit.setPlainText(_translate("Dialog", "Hello World!"))
        self.radioButton_3.setText(_translate("Dialog", "Black    "))
        self.radioButton_2.setText(_translate("Dialog", "Red   "))
        self.radioButton.setText(_translate("Dialog", "Blue"))
        self.pushButton_3.setText(_translate("Dialog", "清空"))
        self.pushButton_2.setText(_translate("Dialog", "确认"))
        self.pushButton.setText(_translate("Dialog", "取消"))
        self.label.setText(_translate("Dialog", "字体样式"))
        self.checkBox_3.setText(_translate("Dialog", "Underline"))
        self.checkBox_2.setText(_translate("Dialog", "Italic"))
        self.checkBox.setText(_translate("Dialog", "Bold"))
        self.label_2.setText(_translate("Dialog", "字体颜色"))


按照之前的单继承方法,我们另写一个文件来测试:

import  sys
from PyQt5.QtWidgets import QApplication, QDialog
from Proj2_dialog import Ui_Dialog

class QmyDialog(QDialog):
    def __init__(self):
        super(QmyDialog, self).__init__()
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
 #   def on_pushButton_3_clicked(self): 这两句不用
  #      self.ui.plainTextEdit.clear()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    MyDialog = QmyDialog()
    MyDialog.show()
    sys.exit(app.exec_())

在这里插入图片描述
这时单击确认和取消按键就可以关闭窗口了。

二、自定义槽函数

假设现在我们想点击清空按键的时候将文本编辑器中的文本全部清除,这就需要自己定义dialog的相关槽函数了。
在这里插入图片描述
右击清空button,选择转到槽函数:
在这里插入图片描述
这是它作为一个pushbutton所拥有的信号,点击OK,会自动跳转到一个c++文件中,这就是关联的槽函数的名称,我们把它复制到自己定义的类中作为一个类方法:
在这里插入图片描述

import  sys
from PyQt5.QtWidgets import QApplication, QDialog
from Proj2_dialog import Ui_Dialog

class QmyDialog(QDialog):
    def __init__(self):
        super(QmyDialog, self).__init__()
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
    def on_pushButton_3_clicked(self): # 这就是自己定义的槽函数
       self.ui.plainTextEdit.clear()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    MyDialog = QmyDialog()
    MyDialog.show()
    sys.exit(app.exec_())

运行,单击清空按键就会发现文本被清除了,完美!
在这里插入图片描述

总结

这里我们生成的c++文件其实没用用上,只是为了查看生成的槽函数的名称,其实我们自己也省略了手动关联的部分,比如相对于内置的槽函数,我们自定义的槽函数少了下面的语句:

        self.pushButton_2.clicked.connect(Dialog.accept) # 这里是确认
        self.pushButton.clicked.connect(Dialog.close)   # 这里是取消

这是因为Qt帮我们自动关联了,只要我们命名的槽函数符合某个规范,例如:on_pushButton_3_clicked(self):,命名规则符合on_<object name>_<signal name>_(<signal parameter>)即可,我们注意到上面自动生成的py文件还包含一句:

        self.pushButton_2.clicked.connect(Dialog.accept) # 这里是确认
        self.pushButton.clicked.connect(Dialog.close)   # 这里是取消
        QtCore.QMetaObject.connectSlotsByName(Dialog)  # 这里是自动建立关联

如果没有后面这句代码,那么我们也要向上面一样手动关联:

self.pushButton_3.clicked.connect(Dialog.on_pushButton_3_clicked)

以上是关于Python Qt GUI设计入门信号与槽函数的主要内容,如果未能解决你的问题,请参考以下文章

Python Qt GUI设计:信号与槽的使用方法(基础篇—7)

Python Qt GUI设计:多线程中信号与槽的使用(基础篇—9)

C++ GUI Qt的建立连接,信号和槽

QT开发(十三)——QT信号与槽机制

QObject三大核心功能——信号与槽

一Qt初尝试,做一个QT计算器《QT 入门到实战》