文章目录
前言
在上一章我们已经讲解了如何使用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>()即可,我们注意到上面自动生成的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)