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, QtWidgets class 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: ignore self.btnClose.clicked.connect(Dialog.close) # type: ignore QtCore.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.translate Dialog.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 sys app = 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_Dialog class 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 QmyDialog app = QApplication(sys.argv)#创建GUI应用程序 mainform = QmyDialog()#创建主窗体 mainform.show()#显示主窗体 sys.exit(app.exec())
运行appMain函数,就可以对窗体进行操作了,一起试一下吧!
创作不易,如果其中有错误尽管私信我哦~💖💖💖💖💖