PyQt---------信号与槽函数的关系

简介: PyQt---------信号与槽函数的关系

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函数,就可以对窗体进行操作了,一起试一下吧!


创作不易,如果其中有错误尽管私信我哦~💖💖💖💖💖


目录
相关文章
|
4天前
|
缓存 监控 程序员
Python中的装饰器是一种特殊类型的声明,它允许程序员在不修改原有函数或类代码的基础上,通过在函数定义前添加额外的逻辑来增强或修改其行为。
【6月更文挑战第30天】Python装饰器是无侵入性地增强函数行为的工具,它们是接收函数并返回新函数的可调用对象。通过`@decorator`语法,可以在不修改原函数代码的情况下,添加如日志、性能监控等功能。装饰器促进代码复用、模块化,并保持源代码整洁。例如,`timer_decorator`能测量函数运行时间,展示其灵活性。
13 0
|
9天前
|
Python
python之print函数
python之print函数
15 0
|
8天前
|
分布式计算 算法 Python
Python函数进阶:四大高阶函数、匿名函数、枚举、拉链与递归详解
Python函数进阶:四大高阶函数、匿名函数、枚举、拉链与递归详解
|
1天前
|
Python
|
1天前
|
API Python
Python学习日记(二:函数和逻辑操作)
Python中的函数和逻辑操作至关重要。函数包括可变和不可变参数。
|
6天前
|
机器学习/深度学习 人工智能 程序员
探索Python宝库:从基础到技能的干货知识(数据类型与变量+ 条件与循环+函数与模块+文件+异常+OOP)
探索Python宝库:从基础到技能的干货知识(数据类型与变量+ 条件与循环+函数与模块+文件+异常+OOP)
7 0
|
8天前
|
Python
经验大分享:python类函数,实例函数,静态函数
经验大分享:python类函数,实例函数,静态函数
11 0
|
8天前
|
Python
|
8天前
|
Python
经验大分享:Python函数返回值
经验大分享:Python函数返回值
|
9天前
|
Python
python函数
python函数
10 0