• QT的信号与槽函数


    一.什么是信号和槽函数

    QT中通过信号(signal)和槽函数(slot)将事件和响应函数连接起来(可以类比MFC中的操作和对应的On开头的响应函数).

    它的优点在于信号和槽函数是松耦合的关系,你可以通过connect将两者连接起来,也可以通过disconnect将两者断开.

    它们的格式如下:

    connect/disconnect(信号的发送者, 具体的信号, 信号的接收者, 信号的处理(槽)).

    二.信号和槽函数的例子

    假如有这样一个需求:在下课的时候,老师说饿了,然后学生去请老师吃饭.

    这样对应到信号和槽函数,如下所示:

    信号与槽示意图

    设计的类图如下所示:

     在widget.cpp中有如下的代码组织,其中讨论了有无函数重载的情况下对应的实现;信号连接信号的用法;断开连接;用Lambda表达式来表示槽函数的方式.

    #include "widget.h"
    #include <QPushButton>
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
    {
        this->te = new Teacher(this);
        this->st = new Student(this);
    
        ///无参信号和槽  
        //当不存在函数重载时,可以直接使用&Teacher::hungry的方式
        //connect(te, &Teacher::hungry, st, &Student::treat);
        //classIsOverNoFoodName(); //也可以如此触发:te->hungry();
    
        //当存在函数重载时,需要使用函数指针.
        void(Teacher:: * teacherSignalVoid)(void) = &Teacher::hungry;
        void(Student:: * studentSlotVoid)(void) = &Student::treat;
        connect(te, teacherSignalVoid, st, studentSlotVoid);
        classIsOverNoFoodName(); //也可以如此触发:te->hungry();
    
    
        ///带参数的信号和槽(如果带参数的函数不存在重载问题,可以直接使用最简单的connect方式,就像无参的那个例子一样.)
        //函数指针 -> 函数地址
        void(Teacher:: * teacherSignal)(QString) = &Teacher::hungry;    //这里的函数指针要指明它是作用域,它是Teacher类下的,不是别的下面的.
        void(Student:: * studentSlot)(QString) = &Student::treat;
        connect(te, teacherSignal, st, studentSlot);
        classIsOver();
    
        ///点击按钮来触发下课
        QPushButton * btn = new QPushButton("classIsOver", this);
        btn->move(100,100);
        this->setFixedSize(600, 300);
        this->setWindowTitle("signalAndSlotDemo");
        //这里把一般的函数也可以作为槽函数来使用.
        //connect(btn, &QPushButton::clicked, this, &Widget::classIsOver);
    
        ///信号连接信号
        //!注意,这里的clicked原型是clicked(bool checked = false),它有一个bool参数,作为它的槽函数要么是一个bool参数,要么是没有参数(即为void);
        connect(btn, &QPushButton::clicked, te, teacherSignalVoid); //此处因为hungry有重载的问题,所以不能够直接使用Teacher::hungry.
    
        ///断开信号
        //disconnect(te, teacherSignalVoid, st, studentSlotVoid);
        //disconnect(btn, &QPushButton::clicked, te, teacherSignalVoid);
    
        //!!!!!!拓展!!!!!!!!!!
        //!!Qt4版本以前连接方式:
        //无参版本:
        //connect(te, SIGNAL(hungry(), st, SLOT(treat());
        //优点:参数直观.  缺点:类型不做检测.
    
        ///Lambda表达式:匿名函数,简便书写.
        [=](){                      //=:值传递
            btn->setText("lambda");
        }();                        //加上后面的()才能算是执行函数
    
        ///利用Lambda表达式实现点击按钮关闭窗口
        connect(btn, &QPushButton::clicked, this, [=](){
            this->close();
        });
    }
    
    Widget::~Widget()
    {
    
    }
    
    void Widget::classIsOver()
    {
        emit te->hungry("kongpochicken");
    }
    
    void Widget::classIsOverNoFoodName()
    {
        emit te->hungry();
    }

    完整的代码位置:https://github.com/StephennQin/QTProjects/tree/master/02_signalAndSlot

    三.信号和槽函数的总结

    1.信号是可以连接信号
    2.一个信号可以连接多个槽函数
    3.多个信号 可以连接 同一个槽函数.
    4.信号和槽函数的参数 必须类型一一对应,就像信号里传递的是QString类型的"宫保鸡丁",那么槽函数里也要用QString类型的foodName来接收.
    5.信号的参数个数可以多于槽函数参数个数.比如上面的clicked原型是clicked(bool checked = false),它有一个bool参数,作为它的槽函数要么是一个bool参数,要么是没有参数(即为void);

      --------------------------------------------------------------------------------------------------------------------

    文章总结自bilibili上的传智播客的视频: https://www.bilibili.com/video/BV1g4411H78N?

    新战场:https://blog.csdn.net/Stephen___Qin
  • 相关阅读:
    2020/10/29
    2020/10/24
    2020/10/28
    2020/10/31周报
    linux shell 中判断字符串为空的正确方法
    20201107 千锤百炼软工人
    20201103 千锤百炼软工人
    20201109 千锤百炼软工人
    20201111 千锤百炼软工人
    20201105 千锤百炼软工人
  • 原文地址:https://www.cnblogs.com/Stephen-Qin/p/13053138.html
Copyright © 2020-2023  润新知