• Qt的信号与槽的使用


    1、信号和槽机制

    信号与槽用于两个对象之间,当一个部件发生改变时,希望其他部件也能了解到该变化,也希望任何对象与其他对象进行通信。

    • Qt封装了具体操作系统的消息机制,遵循经典的GUI消息驱动事件模型。 消息驱动机制

    • QT定义了与操作系统消息相关的自己的概念,即信号与槽。

    • 信号signal是由操作系统产生的消息。

    • 槽slot是程序中的消息处理函数。

    • connect将系统消息绑定到消息处理函数。

    • 信号到槽的连接必须发生在两个QT对象间。

    bool QObject::connect ( 
        const QObject * sender, //发生对象
        const char * signal, //消息名
        const QObject * receiver, //接收对象
        const char *method, //接收对象的成员函数
        Qt::ConnectionType type = Qt::AutoConnection )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    eg:

    connect(ui->btn, &QPushButton::clicked, this, &MainWindow::change_state);
    connect(ui->btn, SIGNAL(clicked()), this, SLOT(change_state()));//qt4
    
    • 1
    • 2

    信号和槽机制的特色和优越性:

    • 信号和槽机制是类型安全的,相关联的信号和槽的参数必须匹配;

    • 信号和槽是松耦合的,信号发送者不知道也不需要知道接受者的信息;

    • 信号和槽可以使用任意类型的任意数量的参数。

      虽然信号和槽机制提供了高度的灵活性,但就其性能而言,还是慢于回调机制的。回调函数 性能差异在应用程序中还是很难体现出来的

    2 、QT中的相关的关键字

    • SIGNAL用于指定消息名
    • SLOT用于指定消息处理函数名
    • Q_OBJECT所以自定义槽的类必须在类声明的开始处加上Q_OBJECT
    • slots用于在类中声明消息处理函数
    • signals用于在哪种声明信号

    3、 使用信号和槽应该注意

    • 需要继承自QObject或其子类;
    • 在类声明的最开始处添加Q_OBJECT宏;
    • 槽中的参数的类型要和信号的参数的类型相对应,且不能比信号的参数多;
    • 信号只用声明,没有定义,且返回值为void类型。
    • 声明一个信号要使用signals关键字,在signals前面不能使用public、private和protected等限定符因为只有定义该信号的类及其子类才可以发射该信号。
    • 一个信号可以关联到多个槽上,多个信号也可以关联到同一个槽上,如果存在多个槽与某个信号相关联,那么,当这个信号被发射时,这些槽将会一个接一个地执行,但是它们执行的顺序是随机的,无法指定它们的执行顺序。
    • 槽是普通的成员函数,也有访问权限。
      • 槽的访问权限决定了谁能够与其相关联。同普通的C++成员函数一样,槽函数也分为三种类型,即public slots、private slots和protected slots
      • public slots:使用publicslots声明的槽表示任何对象都可将信号与之相连接。在组件编程中,可以创建彼此互不了解的对象,将它们的信号与槽进行连接以便信息能够正确的传递。
      • protected slots:使用protected slots声明的槽表示当前类及其子类可以将信号与之相连接。适用于那些槽,它们是类实现的一部分,但是其界面接口却面向外部。
      • private slots:使用private slots声明的槽表示只有类自己可以将信号与之相连接,适用于联系非常紧密的类。
    • 槽函数就是一个普通函数,在没有与信号一起使用的时候,可以以普通成员函数的方式来使用

    4 、信号与槽三种使用方式:

    1、转到槽(快捷方式)

    ​ 鼠标右键点击发送信号的控件,选择转到槽,选择对应的信号,会在.cpp中生成槽函数,在槽函数内部编写要执行的代码(行为)。

    2、自定义槽函数和连接函数

    ​ 在接收信号的类里面声明槽函数,槽函数的定义跟类的普通成员函数定义方式一样。

    ​ 在发送信号和接收信号的对象建立之后代码中使用connet函数进行信号与槽函数的连接

    3、自定义信号、槽函数和连接函数

    ​ 在发送信号的类中自定义一个信号,在声明信号的类或派生类发送.

    ​ 在接收信号的类里面声明槽函数,槽函数的定义跟类的普通成员函数定义方式一样。

    ​ 在发送信号和接收信号的对象建立之后代码中使用connet函数进行信号与槽函数的连接

    自动生成的槽函数命名规范:on_对象名称_对象信号(),在后两种方式中如果槽函数按照这样的命名方式,就可以不写连接。

    5、信号与槽使用小结

    1、信号声明位置,信号发送位置?

    信号声明在发送信号的类中声明(.h)中

    ①自定义一个信号

    signals:://信号不能像普通函数一样使用,也不需要权限声明
    	void mysignal();//信号不需要定义
    
    • 1
    • 2

    ②发送信号

    emit mysignal();
    
    • 1

    2、槽函数声明位置,槽函数定义位置?

    接收信号的类中声明槽函数(.h)

    private slots://槽函数在类中的声明
        void myslot();//槽函数的定义跟类的普通成员函数定义方式一样
    
    • 1
    • 2
    //槽函数定义
    void MainWindow::myslot()
    {
        ui->label_2->setText("完成设置");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    匿名函数方式

    qt5支持 c++11中的lambda表达式

    connect(btn,&QpushBtton::clicked,[=](/*参数*/){
        //函数体
    });
    
    • 1
    • 2
    • 3

    3、connect建立信号和槽函数的链接?

    在同时能够看到信号发送者和信号接收者的地方

    //绑定信号和槽函数
    //    connect(this, SIGNAL(mysignal()), this, SLOT(myslot()));
        connect(this, &MainWindow::mysignal, this, &MainWindow::myslot);
    
    • 1
    • 2
    • 3

    6、信号与槽传递数据

    通过参数来传递

    void send_data(QString msg); void recv_data(QString msg);

    注意:

    (1)信号不带参数,槽函数一定不能带参数

    (2)信号带参数,槽函数可以不带参数,如果槽函数带参数,得保证类型和信号的参数类型一致

    (3)信号参数个数可以是多个,槽函数可以没有,也可以有多个(顺序要与信号的参数一致),也可以有其中的某个

    7、断开连接

    当信号与槽没必要进行保持关联时,可以使用disconnect函数来断开连接

    bool QObject::disconnect ( 
        const QObject * sender, 
        const char * signal, 
        const QObject * receiver, 
        const char *method ) 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    disconnect函数断开发送者中的信号与接收者中的槽函数之间的关联。

    在disconnect函数中0可以用作一个通配符,分别表示任何信号、任何接收对象、接收对象中的任何槽函数。但是发射者sender不能为0,其它三个参数的值可以等于0。

    ①断开与某个对象关联的任何对象

    disconnect(sender,0,0,0);
    //sender->disconnect();
    
    • 1
    • 2

    ②断开与某个特定信号的任何关联

    disconnect(sender,SIGNAL(mySignal()),0,0);
    //sender->disconnect(SIGNAL(mySignal()));
    
    • 1
    • 2

    ③断开两个对象之间的关联

    dixsconnect(sender,0,recevier,0);
    //sender->disconnect(recevier);
    
    • 1
    • 2
  • 相关阅读:
    网站过度优化有哪些预兆?
    「 安全工具介绍 」软件成分分析工具Black Duck,业界排名TOP 1的SCA工具
    学习-Java输入输出之File类之文件创建删除
    Unity编辑器扩展(一)编辑器扩展基础
    golang的管道阻塞问题
    商用车市场「跌跌不休」,主动安全「让位」智能驾驶?
    Nacos OpenAPI清单
    Python之glob
    Qt之数据序列化(结构体序列化,类序列化,含源码+注释)
    Centos 7配置开机自启Springboot项目
  • 原文地址:https://blog.csdn.net/qq_45698138/article/details/126151877