zoukankan      html  css  js  c++  java
  • 第四篇 -- 信号与槽的使用

    学习书籍《Python Qt GUI与数据可视化编程》

    一、信号与槽功能概述

    信号(Signal):就是在特定情况下被发射(emit)的一种通告,例如一个PushButton按钮最常见的信号就是鼠标单击时发射的clicked()信号,一个ComboBox最常见的信号是选择的项变化时发射的CurrentIndexChanged()信号。GUI程序设计的主要内容就是对界面上各组件发射的特定信号进行响应,只需要知道什么情况下发射了哪些信号,然后合理地去响应和处理这些信号就可以了。

    槽(Slot):就是对信号响应的函数。槽实质上是一个函数,它可以被直接调用。槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数会被自动执行。Qt的类一般都有一些内建(build-in)的槽函数,例如QWidget有一个槽函数close(),其功能是关闭窗口。如果将一个PushButton按钮的clicked()信号与窗体的close()槽函数关联,那么点击按钮时就会关闭窗口。

    二、组件的信号与内建槽函数的关联

    1. 先画一个图

    属性设置表格如下:

    对象名 类名称 属性设置 功能
    Dialog QDialog windowTitle="Demo2-3信号与槽" 窗体的类名称是Dialog,objectName不要修改
    textEdit QPlainTextEdit

    Text="PyQt5 编程指南 Python 和 Qt."

    Font.PointSize=20

    Font.bold=True

    用于显示文字,可编辑
    chkBoxUnder QCheckBox Text="Underline" 设置字体的下划线特定
    chkBoxItalix QCheckBox Text="Italic" 设置字体的斜体特性
    chkBoxBold QCheckBox Text="Bold" 设置字体的粗体特性
    radioBlack QRadioButton Text="Black" 设置字体颜色为黑色
    radioRed QRadioButton Text="Red" 设置字体颜色为红色
    radioBlue QRadioButton Text="Blue" 设置字体颜色为蓝色
    btnClear QPushButton Text="清空" 清空文本框内容
    btnOK QPushButton Text="确定" 返回确定,并关闭窗口
    btnClose QPushButton Text="退出" 退出程序

    2. 界面组件布局管理

     

    布局组件 功能
    Vertival Layout 垂直布局,组件自动在垂直方向上分布
    Horizontal Layout 水平布局,组件自动在水平方向上分布
    Grid Layout 网格状布局,网格状布局大小改变时,每个网格的大小都改变
    Form Layout 窗体布局,与网格布局类似。但是只有最右侧的一列网格会改变大小
    Horizontal Spacer 一个用于水平分隔的空格
    Vertical Spacer 一个用于垂直分隔的空格

    使用:先拖一个布局组件到窗体上,例如窗体下方的3个按钮的布局,先放一个Horizontal Layout到窗体上,布局组件会以红色矩形框显示,在向布局组件里拖放3个PushButton和两个Horizontal Spacer,就可以得到3个按钮的水平布局。每个布局还有layoutTopMargin、layoutBottomMargin、layoutLeftMargin、layoutRightMargin这四个属性用于调整布局边框与内部组件之间的上、下、左、右的边距大小。

    在设计窗体的上方有一个工具栏,用于使界面进入不同的设计状态,以及进行布局设计,工具栏商各按钮的功能如下:

    按钮及快捷键 功能
    Edit Widget(F3) 界面设计进入编辑状态,也就是正常的设计状态
    Edit Signals/Slots(F4) 进入信号与槽的可视化设计状态
    Edit Buddies 进入伙伴关系编辑状态,可以设置一个Lable与一个组件成为伙伴关系
    Edit Tab Order 进入Tab顺序编辑状态,Tab顺序是指在键盘上按Tab键时,输入焦点在界面各组件之间跳动的顺序

    3. 组件的信号与内建槽函数的关联

    Qt的界面组件都是从QWidget继承而来的,都支持信号与槽的功能。每个类都有一些内建的信号和槽函数。例如QPushButton按钮类常用的信号是clicked(),在按钮被单击时发射此信号。QDialog是对话框类,它有以下3个内建的槽函数。

    • accept():功能是关闭对话框,表示肯定的选择,例如“确定”。
    • reject():功能是关闭对话框,表示否定的选择,例如“取消”。
    • close():功能是关闭对话框

    这3个槽函数都可以关闭对话框,但是表示对话框的返回值不同,我们希望将“确定”按钮与对话框的accept()槽函数关联,将“退出”按钮与对话框的close()槽函数关联。

    可以在Qt Designer里使用可视化的方式实现信号与槽函数的关联。在Qt Designer里单击上方工具栏里的“Edit Signals/Slots”按钮,窗体进入信号与槽函数编辑状态。

    鼠标点选“确定”按钮,在按住鼠标左键拖动到窗体的空白区域后释放左键,这时出现关联设置对话框

    此对话框里左边的列表框里显示了btnOK的信号(上图显示的是btnClear,因为btnOK之前自己已经关联过,就不重复关联了),选择clicked(),右边的列表框里显示了Dialog的槽函数,选择accept(),然后单击“OK”按钮。同样的方法可以将btnClose的clicked()信号与Dialog的close()槽函数关联,值得注意的是,如果没有看到close()槽函数,可以将下方的“Show signals and slots inherited from QWidget”打勾。

    设置好这两个按钮的信号与槽关联后,在窗体右下方的Signals Slots编辑器里就显示了这两个关联。实际上可以直接在Signals Slots编辑器进行某个组件的内建信号与其他组件的内建槽函数关联。

    4. 将ui文件转换为py

    Dialog.py

    # -*- coding: utf-8 -*-
    
    # Form implementation generated from reading ui file 'Dialog.ui'
    #
    # Created by: PyQt5 UI code generator 5.13.0
    #
    # WARNING! All changes made in this file will be lost!
    
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class Ui_Dialog(object):
        def setupUi(self, Dialog):
            Dialog.setObjectName("Dialog")
            Dialog.resize(400, 300)
            self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
            self.verticalLayout.setObjectName("verticalLayout")
            self.groupBox = QtWidgets.QGroupBox(Dialog)
            self.groupBox.setTitle("")
            self.groupBox.setObjectName("groupBox")
            self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.groupBox)
            self.horizontalLayout_3.setObjectName("horizontalLayout_3")
            self.chkBoxUnder = QtWidgets.QCheckBox(self.groupBox)
            self.chkBoxUnder.setObjectName("chkBoxUnder")
            self.horizontalLayout_3.addWidget(self.chkBoxUnder)
            self.chkBoxItalic = QtWidgets.QCheckBox(self.groupBox)
            self.chkBoxItalic.setObjectName("chkBoxItalic")
            self.horizontalLayout_3.addWidget(self.chkBoxItalic)
            self.chkBoxBold = QtWidgets.QCheckBox(self.groupBox)
            self.chkBoxBold.setObjectName("chkBoxBold")
            self.horizontalLayout_3.addWidget(self.chkBoxBold)
            self.verticalLayout.addWidget(self.groupBox)
            self.groupBox_2 = QtWidgets.QGroupBox(Dialog)
            self.groupBox_2.setTitle("")
            self.groupBox_2.setObjectName("groupBox_2")
            self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.groupBox_2)
            self.horizontalLayout_4.setObjectName("horizontalLayout_4")
            self.radioBlack = QtWidgets.QRadioButton(self.groupBox_2)
            self.radioBlack.setObjectName("radioBlack")
            self.horizontalLayout_4.addWidget(self.radioBlack)
            self.radioRed = QtWidgets.QRadioButton(self.groupBox_2)
            self.radioRed.setObjectName("radioRed")
            self.horizontalLayout_4.addWidget(self.radioRed)
            self.radioBlue = QtWidgets.QRadioButton(self.groupBox_2)
            self.radioBlue.setObjectName("radioBlue")
            self.horizontalLayout_4.addWidget(self.radioBlue)
            self.verticalLayout.addWidget(self.groupBox_2)
            self.plainTextEdit = QtWidgets.QPlainTextEdit(Dialog)
            font = QtGui.QFont()
            font.setPointSize(20)
            font.setBold(True)
            font.setWeight(75)
            self.plainTextEdit.setFont(font)
            self.plainTextEdit.setObjectName("plainTextEdit")
            self.verticalLayout.addWidget(self.plainTextEdit)
            self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
            self.horizontalLayout_2.setObjectName("horizontalLayout_2")
            spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
            self.horizontalLayout_2.addItem(spacerItem)
            self.btnClear = QtWidgets.QPushButton(Dialog)
            self.btnClear.setObjectName("btnClear")
            self.horizontalLayout_2.addWidget(self.btnClear)
            spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
            self.horizontalLayout_2.addItem(spacerItem1)
            self.btnOK = QtWidgets.QPushButton(Dialog)
            self.btnOK.setObjectName("btnOK")
            self.horizontalLayout_2.addWidget(self.btnOK)
            self.btnClose = QtWidgets.QPushButton(Dialog)
            self.btnClose.setObjectName("btnClose")
            self.horizontalLayout_2.addWidget(self.btnClose)
            self.verticalLayout.addLayout(self.horizontalLayout_2)
    
            self.retranslateUi(Dialog)
            self.btnOK.clicked.connect(Dialog.accept)
            self.btnClose.clicked.connect(Dialog.close)
            QtCore.QMetaObject.connectSlotsByName(Dialog)
    
        def retranslateUi(self, Dialog):
            _translate = QtCore.QCoreApplication.translate
            Dialog.setWindowTitle(_translate("Dialog", "Demo2-3信号与槽"))
            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.plainTextEdit.setPlainText(_translate("Dialog", "PyQt5 编程指南
    "
    "Python 和 Qt."))
            self.btnClear.setText(_translate("Dialog", "清空"))
            self.btnOK.setText(_translate("Dialog", "确定"))
            self.btnClose.setText(_translate("Dialog", "退出"))
    View Code

    5. 窗体业务逻辑类文件myDialog.py

    # # 与UI窗体类对应的业务逻辑类
    import sys
    from PyQt5.QtWidgets import QDialog, QApplication
    from Dialog import Ui_Dialog
    
    
    class QmyDialog(QDialog):
        def __init__(self, parent=None):
            super().__init__(parent)  # 调用父类构造函数,创建QWidget窗体
            self.ui = Ui_Dialog()  # 创建UI对象
            self.ui.setupUi(self)  # 构造UI
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)  # 创建app,用QApplication类
        form = QmyDialog()
        form.show()
        sys.exit(app.exec_())
    View Code

    6. 应用程序主程序文件appMain.py

    # # GUI应用程序主程序
    import sys
    from PyQt5.QtWidgets import QApplication
    from myDialog import QmyDialog
    
    app = QApplication(sys.argv)  # 创建GUI应用程序
    mainform = QmyDialog()  # 创建主窗体
    mainform.show()  # 显示主窗体
    sys.exit(app.exec_())
    View Code

    notes: 程序myDialog.py可以当做主程序直接运行,但是建议单独编写一个主程序文件appMain.py,appMain.py的功能是创建应用程序和主窗体,然后显示主窗体,并开始运行应用程序。它将myDialog.py文件的测试运行部分单独拿出来作为一个文件。当一个应用程序有多个窗体,并且窗体之间有数据传递时,appMain.py负责创建应用程序的主窗体并运行起来,这样使整个应用程序的结构更清晰。

  • 相关阅读:
    数据结构小练习
    【BZOJ 3652】大新闻 数位dp+期望概率dp
    【BZOJ 3326】[Scoi2013]数数 数位dp+矩阵乘法优化
    【Codeforces 506E】Mr.Kitayuta’s Gift&&【BZOJ 4214】黄昏下的礼物 dp转有限状态自动机+矩阵乘法优化
    【BZOJ 4455】 [Zjoi2016]小星星 容斥计数
    凸包小结
    Matrix-Tree定理题表
    PLAN OF HEOI(unfinished)
    (ex)BSGS题表
    exBSGS板子
  • 原文地址:https://www.cnblogs.com/smart-zihan/p/12642624.html
Copyright © 2011-2022 走看看