1.信号(Signal)
信号是在特定情况下被发射的一种通告。举例:
PushButton 的信号是鼠标单击时发射的 clicked 信号
2.槽(Slot)
对信号相应的函数。举例:
QWidget 有一个槽函数,功能是关闭窗口
3.信号与槽的关系
一个信号可以关联多个槽函数
一个信号可以关联其他信号
信号的参数可以是任何 Python 数据类型
一个槽函数可以和多个信号关联
关联可以是直接的(同步)或排队的(异步)
可以在不同的线程之间建立关联 (信号与槽可以断开关联)
关于槽函数与信号的实例:
在PyQt中做以下窗口:
可以实现在字体下划下划线,斜体,变粗,以及字体变色
窗口链接我放这里:
链接:https://pan.baidu.com/s/1LzahreskBrSH8JfYZeaQjQ
提取码:cyss
注:
我在这里重新做过排序
设置信号和槽
在这里我们设置对话框类 Qdialog 内置槽函数
accept():关闭对话框,表示肯定的选择,例如“确定”
reject():关闭对话框,表示否定的选择,例如“取消”
close():关闭对话框
点击右上边的Edit Signals
点击确定按钮
点击clicked(),接着点击accept()
同理点击关闭按钮,点击clicked(),close()
就可以在Signal and Slots Editor中看到
在Eric中创建该项目
这里就是刚刚建好的信号与槽的关联
(1)为做演示,我在Ui_Dialog中添加了一些代码,用于在TextEdit中显示文字
代码如下:
# Form implementation generated from reading ui file 'D:\cys\Dialog.ui'
#
# Created by: PyQt6 UI code generator 6.5.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.from PyQt6 import QtCore, QtGui, QtWidgetsclass Ui_Dialog(object):def setupUi(self, Dialog):Dialog.setObjectName("Dialog")Dialog.resize(471, 452)self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)self.verticalLayout.setObjectName("verticalLayout")self.groupBox1 = QtWidgets.QGroupBox(parent=Dialog)self.groupBox1.setTitle("")self.groupBox1.setObjectName("groupBox1")self.horizontalLayout = QtWidgets.QHBoxLayout(self.groupBox1)self.horizontalLayout.setObjectName("horizontalLayout")self.chkBoxUnder = QtWidgets.QCheckBox(parent=self.groupBox1)self.chkBoxUnder.setChecked(False)self.chkBoxUnder.setObjectName("chkBoxUnder")self.horizontalLayout.addWidget(self.chkBoxUnder)self.chkBoxItalic = QtWidgets.QCheckBox(parent=self.groupBox1)self.chkBoxItalic.setObjectName("chkBoxItalic")self.horizontalLayout.addWidget(self.chkBoxItalic)self.chkBoxBold = QtWidgets.QCheckBox(parent=self.groupBox1)self.chkBoxBold.setObjectName("chkBoxBold")self.horizontalLayout.addWidget(self.chkBoxBold)self.verticalLayout.addWidget(self.groupBox1)self.groupBox = QtWidgets.QGroupBox(parent=Dialog)self.groupBox.setTitle("")self.groupBox.setObjectName("groupBox")self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.groupBox)self.horizontalLayout_2.setObjectName("horizontalLayout_2")self.radioBlack = QtWidgets.QRadioButton(parent=self.groupBox)self.radioBlack.setObjectName("radioBlack")self.horizontalLayout_2.addWidget(self.radioBlack)self.radioRed = QtWidgets.QRadioButton(parent=self.groupBox)self.radioRed.setObjectName("radioRed")self.horizontalLayout_2.addWidget(self.radioRed)self.radioBlue = QtWidgets.QRadioButton(parent=self.groupBox)self.radioBlue.setObjectName("radioBlue")self.horizontalLayout_2.addWidget(self.radioBlue)self.verticalLayout.addWidget(self.groupBox)self.plainTextEdit = QtWidgets.QPlainTextEdit(parent=Dialog)self.plainTextEdit.setObjectName("plainTextEdit")self.verticalLayout.addWidget(self.plainTextEdit)self.horizontalLayout_3 = QtWidgets.QHBoxLayout()self.horizontalLayout_3.setObjectName("horizontalLayout_3")spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)self.horizontalLayout_3.addItem(spacerItem)self.btnClear = QtWidgets.QPushButton(parent=Dialog)self.btnClear.setObjectName("btnClear")self.horizontalLayout_3.addWidget(self.btnClear)spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)self.horizontalLayout_3.addItem(spacerItem1)self.btnOK = QtWidgets.QPushButton(parent=Dialog)self.btnOK.setObjectName("btnOK")self.horizontalLayout_3.addWidget(self.btnOK)self.btnClose = QtWidgets.QPushButton(parent=Dialog)self.btnClose.setObjectName("btnClose")self.horizontalLayout_3.addWidget(self.btnClose)self.verticalLayout.addLayout(self.horizontalLayout_3)self.retranslateUi(Dialog)self.btnOK.clicked.connect(Dialog.accept) # type: ignoreself.btnClose.clicked.connect(Dialog.close) # type: ignoreQtCore.QMetaObject.connectSlotsByName(Dialog)Dialog.setTabOrder(self.chkBoxUnder, self.chkBoxItalic)Dialog.setTabOrder(self.chkBoxItalic, self.chkBoxBold)Dialog.setTabOrder(self.chkBoxBold, self.radioBlack)Dialog.setTabOrder(self.radioBlack, self.radioRed)Dialog.setTabOrder(self.radioRed, self.radioBlue)Dialog.setTabOrder(self.radioBlue, self.plainTextEdit)Dialog.setTabOrder(self.plainTextEdit, self.btnClear)Dialog.setTabOrder(self.btnClear, self.btnClose)def retranslateUi(self, Dialog):_translate = QtCore.QCoreApplication.translateDialog.setWindowTitle(_translate("Dialog", "Dialog"))self.chkBoxUnder.setText(_translate("Dialog", "Underline"))self.chkBoxItalic.setText(_translate("Dialog", "Italic"))self.chkBoxBold.setText(_translate("Dialog", "Bold"))self.radioBlack.setText(_translate("Dialog", "Black"))self.radioRed.setText(_translate("Dialog", "Red"))self.radioBlue.setText(_translate("Dialog", "Blue"))self.btnClear.setText(_translate("Dialog", "清空"))self.btnOK.setText(_translate("Dialog", "确定"))self.btnClose.setText(_translate("Dialog", "关闭"))def do_setTextEdit(self, Dialog):self.plainTextEdit.setPlainText("Beautiful is bestter than ugly.")self.plainTextEdit.appendPlainText("Explicit is better than implicit.")self.plainTextEdit.appendPlainText("Simple is better than complex.")self.plainTextEdit.appendPlainText("Complex is better than complicated.")self.plainTextEdit.appendPlainText("Flat is better than nested.")self.plainTextEdit.appendPlainText("Sparse is better than dense.")if __name__ == "__main__":import sysapp = QtWidgets.QApplication(sys.argv)Dialog = QtWidgets.QDialog()ui = Ui_Dialog()ui.setupUi(Dialog)Dialog.show()sys.exit(app.exec())
注:在Ui_Dialog中实现信号与槽关联的代码:
QtCore.QMetaObject.connectSlotsByName(Dialog)
他的功能是搜索 Dialog 窗体上的所有从属组件,将匹配的信号和槽函数关联起来。
只有符合命名规则的槽函数才会被匹配。不符合命名规则的函数不能自动与信号关联
(2)创建myDialog.py
按照 界面与业务逻辑分离且界面独立封装的方式 定义一个类 QmyDialog,保存为myDialog.py。
函数代码如下:
import sys
from PyQt6.QtWidgets import QApplication, QDialog
from PyQt6.QtCore import pyqtSlot
from PyQt6.QtGui import QPalette
from PyQt6.QtCore import Qt
from Ui_Dialog import Ui_Dialogclass QmyDialog(QDialog):def __init__(self, parent=None):
#在 QmyDialog 的构造函数__init__中创建了窗体类的实例对象 self.ui,并调用了
#setupUi()函数super().__init__(parent)#调用父类构造函数,创建窗体self.ui=Ui_Dialog()#创建UI对象self.ui.setupUi(self)#构造UI界面self.ui.do_setTextEdit(self)self.ui.radioBlack.clicked.connect(self.do_setTextColor)self.ui.radioRed.clicked.connect(self.do_setTextColor)self.ui.radioBlue.clicked.connect(self.do_setTextColor)def on_btnClear_clicked(self):self.ui.plainTextEdit.clear()def on_chkBoxBold_toggled(self, checked):font=self.ui.plainTextEdit.font()font.setBold(checked)self.ui.plainTextEdit.setFont(font)def on_chkBoxUnder_clicked(self):checked=self.ui.chkBoxUnder.isChecked()font=self.ui.plainTextEdit.font()font.setUnderline(checked)self.ui.plainTextEdit.setFont(font)@pyqtSlot(bool) #修饰符指定参数类型,用于overload的信号 def on_chkBoxItalic_clicked(self, checked):font=self.ui.plainTextEdit.font()font.setItalic(checked)self.ui.plainTextEdit.setFont(font)def do_setTextColor(self):plet=self.ui.plainTextEdit.palette()if(self.ui.radioBlack.isChecked()):plet.setColor(QPalette.ColorRole.Text, Qt.GlobalColor.black)elif(self.ui.radioRed.isChecked()):plet.setColor(QPalette.ColorRole.Text, Qt.GlobalColor.red)elif(self.ui.radioBlue.isChecked()):plet.setColor(QPalette.ColorRole.Text, Qt.GlobalColor.blue)self.ui.plainTextEdit.setPalette(plet)if __name__=="__main__":#用于当前窗体测试app=QApplication(sys.argv)#创建GUI应用程序form=QmyDialog()#创建窗体form.show()sys.exit(app.exec())
对代码的解释:
on_btnClear_clicked这类,按钮对应的槽函数:
点击clicked()
接着,复制这个函数名,在myDialog中编写代码,其他按钮也是类似操作
注意:对overload型信号的处理有所不同
在 Qt Creator 中为 Italic 复选框设置槽函数,选择 clicked(bool)
记下函数名,他是带参数的
注意有一个 clicked(),还有一个 clicked(bool)。这两个都是 clicked 信号。 默认情况下,
connectSlotsByName 只会关联默认的不带参数的 clicked 信号,不会关联带参数的
clicked(bool)信号。
要解决这个问题,需要使用 @pyqtSlot 修饰符 ,将函数的参数类型声明清楚,例如:
@pyqtSlot(bool) #修饰符指定参数类型,用于overload的信号 def on_chkBoxItalic_clicked(self, checked):font=self.ui.plainTextEdit.font()font.setItalic(checked)self.ui.plainTextEdit.setFont(font)
同时要新增import模块
from PyQt6.QtCore import pyqtSlot
对于颜色的设置要实现设置颜色的三个 RadioButton 按钮的 clicked()信号与同一个槽函数关联
我们添加如下自定义槽函数
def do_setTextColor(self):plet=self.ui.plainTextEdit.palette()if(self.ui.radioBlack.isChecked()):plet.setColor(QPalette.ColorRole.Text, Qt.GlobalColor.black)elif(self.ui.radioRed.isChecked()):plet.setColor(QPalette.ColorRole.Text, Qt.GlobalColor.red)elif(self.ui.radioBlue.isChecked()):plet.setColor(QPalette.ColorRole.Text, Qt.GlobalColor.blue)self.ui.plainTextEdit.setPalette(plet)
同时在构造函数中关联信号和槽函数
self.ui.radioBlack.clicked.connect(self.do_setTextColor)self.ui.radioRed.clicked.connect(self.do_setTextColor)self.ui.radioBlue.clicked.connect(self.do_setTextColor)
这样就可以实现按按钮变换颜色了
(3)创建appMain.py
myDialog.py 可以当作主程序直接运行,但是建议单独编写一个主程序文件 appMain.py。
该文件的功能是创建应用程序和主窗体,然后显示主窗体,并开始运行应用程序。
appMain.py 将 myDialog.py 文件的测试运行部分单独拿出来作为一个文件。
当一个应用程序有多个窗体,并且窗体之间有数据传递时,appMain.py 负责创建应用程序
的主窗体并运行起来,这样使整个应用程序的结构更清晰
代码如下:
import sys
from PyQt6.QtWidgets import QApplication
from myDialog import QmyDialogapp = QApplication(sys.argv)#创建GUI应用程序
mainform = QmyDialog()#创建主窗体
mainform.show()#显示主窗体
sys.exit(app.exec())
运行appMain函数,就可以对窗体进行操作了,一起试一下吧!
创作不易,如果其中有错误尽管私信我哦~💖💖💖💖💖
顺便点个赞鼓励一下作者吧⸜(●˙▾˙●)⸝⸜(●˙▾˙●)⸝