QT中connect函数的几种用法详解总结

前言

信号与槽机制是QT非常核心的东西,通过信号与槽我们可以将不同的部分有机的结合起来,使得各个组件之间的交互简单高效,信号与曹槽像是设计模式中的观察者模式(我自己觉得是这样),只关心信号何时发来,以及做如何相应,组件之间可以异步或者同步去处理事情。

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

槽(Slot):就是对信号响应的函数。槽就是一个函数,与一般的C++函数是一样的,可以定义在类的任何部分(public、private 或 protected),可以具有任何参数,也可以被直接调用。槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。

一、基本形式

官方文档弄下来的:
[static] QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection);
默认是五个参数,关于最后一个参数的具体使用说明参考:信号与槽的连接方式
这个函数的原型就这样,试着看了一下有8个该函数的重载,第一个参数发送者,第二个信号,第三个接收者,第四个接收者的响应函数。
发送者和接受者可以是同一个QObject,在GUI里面我们可以认为一个界面是一个QObject,注意信号与槽的参数要对应上。
界面:
在这里插入图片描述
为此我做个一个小demo,自己测试也通了:
如下头文件:

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButton_5_clicked(); //自动生成的槽函数
    void pushButon1_clicked();      //自定义的1-4按钮的槽函数
    void pushButon2_clicked();
    void pushButon3_clicked();
    void pushButon4_clicked(int i);
signals:
    // void onClicked();            //重载信号
    void sig_add(int i);
private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

.CPP文件

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "qglobal.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //第一种方式
    connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(pushButon1_clicked()));
   // connect(ui->pushButton,SIGNAL(clicked),ui->pushButton,SLOT(pushButon1_clicked()));
    //第二种方式
    connect(ui->pushButton_2,&QPushButton::clicked,this,&::MainWindow::pushButon2_clicked);
   // connect(ui->pushButton_2, static_cast<void (QPushButton::*)(bool)>(&QPushButton::clicked), this, SLOT(pushButon2_clicked()));
    //第三种方式
        // connect(ui->pushButton_2, static_cast<void (QPushButton::*)(bool)>(&QPushButton::clicked),   
        //            this,SLOT(pushButon2_clicked()));
        //第2参数转换其实是一个函数指针,等价下面的代码
        //void (QPushButton::*ff)(bool)=&QPushButton::clicked;
        // connect(ui->pushButton_2, ff, this, SLOT(pushButon2_clicked()));
    connect(ui->pushButton_3, QOverload<bool>::of(&QPushButton::clicked),this,&::MainWindow::pushButon3_clicked);
    //第四种方式
    connect(ui->pushButton_4, QOverload<bool>::of(&QPushButton::clicked),[=](bool check){
                   ui->textBrowser->setText("按钮4信号绑定成功");
           });
//    connect(ui->pushButton_4, static_cast<void (QPushButton::*)(bool)>(&QPushButton::clicked), this, [=](bool check){
//                    ui->textBrowser->setText("按钮4信号绑定成功");
//            });


}
MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_5_clicked()
{
    ui->textBrowser->setText(QString("按钮5系统生成信号绑定成功"));
}
void MainWindow::pushButon1_clicked()
{
    ui->textBrowser->setText("按钮1信号绑定成功");
}

void MainWindow::pushButon2_clicked()
{
    ui->textBrowser->setText("按钮2信号绑定成功");
}

void MainWindow::pushButon3_clicked()
{
    ui->textBrowser->setText("按钮3信号绑定成功");
    emit sig_add(4);
}

void MainWindow::pushButon4_clicked(int i)
{
    ui->textBrowser->setText("按钮4信号绑定成功");
}

整个工程完整代码(一个积分)。

二、Connect几种方式

方式一

这应该是QT4.0最为传统的方法,其实很多时候用这个还是很清晰的:

    //第一种方式
    connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(pushButon1_clicked()));
   // connect(ui->pushButton,SIGNAL(clicked),ui->pushButton,SLOT(pushButon1_clicked()));

方式二

这应该是QT5.0之后退出来的绑定方法,去掉了之前的宏,感觉更清爽了,我用的还是比较多了

 connect(ui->pushButton_2,&QPushButton::clicked,this,&::MainWindow::pushButon2_clicked);

方式三

C++11出来之后,新的特性就出来,static_cast 用法

    //第三种方式
        // connect(ui->pushButton_2, static_cast<void (QPushButton::*)(bool)>(&QPushButton::clicked),   
        //            this,SLOT(pushButon2_clicked()));
        //第2参数转换其实是一个函数指针,等价下面的代码
        //void (QPushButton::*ff)(bool)=&QPushButton::clicked;
        // connect(ui->pushButton_2, ff, this, SLOT(pushButon2_clicked()));
    connect(ui->pushButton_3, QOverload<bool>::of(&QPushButton::clicked),this,&::MainWindow::pushButon3_clicked);

方式四

目前我用得最多的方式,一开始对lamda表达式感觉困惑,用多了发现还真的很方便,最大的好处就是不需要去定义槽函数了,很简洁。

connect(ui->pushButton_4, QOverload<bool>::of(&QPushButton::clicked),[=](){
                   ui->textBrowser->setText("按钮4信号绑定成功");
           });
//    connect(ui->pushButton_4, static_cast<void (QPushButton::*)(bool)>(&QPushButton::clicked), this, [=](bool check){
//                    ui->textBrowser->setText("按钮4信号绑定成功");
//            });

方法四。在后面lamda表达式 前面可以使用前面几种方法任何部分,相当于槽函数变成一个表达式。
比如可以这样:

connect(ui->pushButton_2,&QPushButton::clicked,this,[=](bool check){
                   ui->textBrowser->setText("按钮4信号绑定成功");

其实在正常使用过程中,比如添加一个按钮,需要点击按钮去执行相应的事情,就会右键,选择相对应的信号,系统会自动把你信号与槽函数对应上,很多情况下是不需要去手动去写的。但是在VS下开发QT的时候(有人喜欢VS的界面,同时VS在调试时候比QT更方便),信号与槽需要手动去绑定,这就需要在写槽函数的时候如果按照系统的规则命名,则会自动的帮你和对应的信号连接起来;如果我们在Qt中自定义信号与槽函数的时候最好不要按照系统的命名去做,省去可能绑定的不确定。
在这里插入图片描述

总结

QT在不断发展壮大中,其实内部有很多值得学习借鉴的地方,在跨平台编译过程中,Qt有着很大优势,在绑定信号与槽函数的时候一定要注意函数是不是带括号的问题。有可能就会出现不匹配的错误。

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

疯狂的挖掘机

谢谢大家的厚爱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值