• 【Qt】- 信号和槽函数


    🤖🤖🤖🤖 欢迎浏览本博客 🤖🤖🤖🤖
    😆😆😆😆😆😆😆大家好,我是:我菜就爱学😆😆😆😆😆😆😆一名刚刚入行的小白👻👻
    👻👻从事方向:计算机视觉 🔔🔔我菜就爱学,分享有误,欢迎大佬指出🔔🔔
    🌏🌏🌏本篇介绍:按钮QPushBUtton、对象树、信号和槽函数


    1 按钮空间常用的API(QPushButton)

    1)Qt帮助文档QPushButton控件说明

    在这里插入图片描述

    2)按钮空间的头文件

    #include 
    
    • 1

    3)创建一个按钮

    QPushButton * btn=new QPushButton;
    
    • 1

    4)按钮相关操作

    //显示按钮
    //btn->show();//默认自己单独以顶层的方式弹出窗口控件
    //该示例是为了让按钮btn对象依赖在mywidget窗口中
    btn->setParent(this);
    //显示按钮文本
    btn->setText("第一个按钮");
    
    //创建第二个按钮,有一个不足就是创建的窗口是依据控件的大小
    QPushButton * btn2=new QPushButton("第二个按钮",this);
    
    //移动第二个按钮,不然第二个按钮默认出现的位置会覆盖第一个按钮
    btn2->move(100,100);
    
    //重置按钮的大小
     btn2->resize(200,50);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    5)窗口相关操作

     //重置窗口的大小,通过拖拽可以改变窗口大小
        resize(600,400);
    
        //设置固定窗口大小
        setFixedSize(600,400);
    
        //设置窗口的标题
        setWindowTitle("第一个窗口程序");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    2 对象树(了解即可)

    说明:在创建QObject对象时,可以提供一个其父对象,创建这个QObject对象会自动添加到其父对象的children()列表。当对父对象析构的时候,这个列表的所有对象也会被析构。一定程度上简化内存回收机制。

    • 构造函数,是编译器默认提供的。无返回值(不是void,而是真的没有)函数名是当前类名,无参,函数体代码为空,定义对象时,自动调用,我们主要用来初始化类成员属性。
    • 析构函数,也是编译器默认提供。析构函数只允许有一个,也是无参的,用来回收成员申请的额外空间,在对象生命周期结束之前(对象回收前)自动调用,一旦我们手动构造了析构函数,编译器默认的析构函数将不再提供
    public:
        myWidget(QWidget *parent = 0);  //构造函数
        ~myWidget();    //析构函数
    };
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    3 Qt窗口的坐标体系

    坐标体系:以左上角为原点(0,0),X向右增加,Y向下增加

    4 信号和槽

    说明:信号槽是 Qt 框架引以为豪的机制之一。所谓信号槽,实际就是观察者模式当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号**。也就是说,**当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。(这里提一句,Qt 的信号槽使用了额外的处理来实现,并不是 GoF 经典的观察者模式的实现方式。)

    在这里插入图片描述

    4.1 connect()函数

    说明:点击按钮,实现窗口的关闭

    //参数1   信号的发送者,参数2  发送信号(函数的地址)  参数3  信号的接收者 参数4  处理的槽函数(函数地址)
    connect(myBtn,&QPushButton::clicked,this,&myWidget::close);
    
    • 1
    • 2
    4.2 自定义的信号和槽

    (1)自定义的信号:

    • 自定义信号,写到signals下
    • 返回值是void,只需要声明,不需要实现
    • 可以带参数,可以重载
    //自定义的信号
    signals:
        void hungray();
    public slots:
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5

    (2)自定义的槽函数

    • 早期的Qt版本,必须写到public sloat,高级版本可以写到public或者全局下
    • 返回值是void,需要声明,需要实现
    • 可以有参数,可以重载
    signals:
    //自定义的槽
    public slots:
        void treat();   //在student.cpp中实现
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5

    (3)案例分析

    设计需求:

    • Teacher类 老师类
    • Student类 学生类
    • 场景:下课后,老师会触发信号,肚子饿了,学生高呼请客吃饭

    widget.cpp:

    • emit:触发自定义信号的函数(如此案例,下课了是触发的自定义信号)
    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
        //创建一个老师对象
        this->zt=new Teacher(this);
        resize(600,400);
    
        //创建一个学生对象
        this->st= new Student(this);
    
        //老师饿了,学生会请客连接,缺少一个下课的方法触发
        connect(zt,&Teacher::hungray,st,&Student::treat);
        //调用下课函数
        ClassIsOver();
    
    }
    void Widget::ClassIsOver()
    {
        //下课函数,触发后,老师就会饿了
        emit zt->hungray();
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    teacher.cpp:

    #include "teacher.h"
    #include
    Teacher::Teacher(QObject *parent) : QObject(parent)
    {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    student.cpp:

    #include "student.h"
    #include    //打印输出的头文件
    Student::Student(QObject *parent) : QObject(parent)
    {
    
    }
    void Student::treat()
    {
        qDebug()<<"请客去吃饭吧";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    4.3 自定义的信号和槽发生重载的解决

    说明:重载,简单说,就是函数或者方法有相同的名称,但是参数列表不相同的情形,这样的同名不同参数的函数或者方法之间,互相称之为重载函数或者方法。

    注意:

    1)出现重载的话,有参和无参在调用时无法区分,需要处理一下

     //连接带参数的信号和槽
        //若是还是按照上述方法连接,无法区分带参和不带参
        //利用函数指针 -> 明确函数的地址
        //函数指针:函数返回值类型 (* 指针变量名)(函数参数列表)
        void(Teacher:: *teacherSignal)(QString)=&Teacher::hungray;
        void(Student:: *studentSlots)(QString)=&Student::treat;
        connect(zt,teacherSignal,st,studentSlots);
        ClassIsOver();
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2)如参数用QSting类型,则输出的参数带引号:请老师吃东西,老师要吃: “北京烤鸭”。所以要把QSting类型->char * 类型

    方法:QString -> QByteArray(.toUtf8())->char *()

    qDebug()<<"请老师吃东西,老师要吃:"<<foodName.toUtf8().data();
    
    • 1
    4.4 信号连接信号

    重新需求:点击一个下课的按钮,再下课。

    1)点击按钮,触发下课,然后老师饿了->进而学生请客吃饭

     QPushButton * btn= new QPushButton("下课",this);
        //点击按钮,触发下课
     connect(btn,&QPushButton::clicked,this,&Widget::ClassIsOver);
    
    • 1
    • 2
    • 3

    2)无参信号和槽的连接:不需要再触发下课了,老师直接饿了,然后学生直接请客吃饭

    void(Teacher:: *teacherSignal2)(void)=&Teacher::hungray;
    void(Student:: *studentSlots2)(void)=&Student::treat;
    connect(zt,teacherSignal2,st,studentSlots2);
    //信号连接信号
    connect(btn,&QPushButton::clicked,zt,teacherSignal2);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3)断开信号连接

    disconnect(zt,teacherSignal2,st,studentSlots2);
    
    • 1

    4)信号和槽函数的拓展

    • 信号可以连接信号
    • 一个信号可以连接多个槽函数
    • 多个信号 可以连接 同一个槽函数
    • 信号和槽函数的参数,必须类型一一对应
    • 信号的参数可以多余槽函数参数的个数,但是槽函数的类型要与信号的类型一致
  • 相关阅读:
    C#语言async, await 简单介绍与实例(入门级)
    systemctl start docker启动报错:Job for docker.service failed because the
    Ubuntu22.04桌面版的 mkdir , mkdir -p 命令笔记2221107
    NEFU离散数学实验3-递推方程
    构建mono-repo风格的脚手架库
    交换机与路由技术-12-单臂路由
    【uni-app】
    stm32 硬件spi半双工三线的一些研究心得
    ERP有哪些系统?运用在哪些行业?
    《教练型管理者》读书笔记-第1篇 【教练原则】
  • 原文地址:https://blog.csdn.net/qq_44859533/article/details/126920008