QT-2-信号与槽

信号与槽

信号与槽是Qt在C++的基础上新增的特性,类似于Java、C#回调的机制,但是使用起来更加方便,可以很容易做出不同组件之间的函数被动调用,是一种通信的机制。

信号是一种函数

槽也是一种函数

要使用信号函数与槽函数,有两个先决条件:

  • 通信的对象必须是从QObject派生出来的

  • 类中必须要加入O_OBJECT宏

函数原型

QObject::connect(const QObject * sender,

const char * signal,

const QObject * receiver,

const char * method) [static]

参数一:发射者,是信号函数的调用对象

参数二:信号函数,是在某些条件下系统自动触发的函数,在外面套上SIGNAL()

参数三:接收者,是执行槽函数的对象。

参数四:槽函数,当信号发射时要一并执行的函数,在外面套上SLOT()

接收者绑定了发射者的信号,一旦发射者发出此信号,接收者就自动执行槽函数。

信号槽除了可以连接之外,也可以断开连接,断开连接后之前连接的信号槽就不生效了。断开连接常见的方式有两种。

  • 自动断连

当发射者或接收者对象销毁时,信号槽也会自动断开连接。

  • 手动断连

可以使用disconnect函数断开之前连接的信号槽,其参数与connect一样。

三种绑定方式

下面依次通过三种信号槽绑定的方式来进行讲解。

1. 自带信号→自带槽

无论信号函数,还是槽函数,都不需要自己编写,只需要查阅文档找出即可。

【例子】点击按钮,关闭窗口。

发射者:按钮对象

信号函数:clicked

接收者:窗口对象

槽函数:close

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton *btn;
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    btn = new QPushButton("关闭",this);
    btn->move(200,200);

    // 点击按钮,关闭窗口
    connect(btn,SIGNAL(clicked()),this,SLOT(close()));
    // 断开连接
//    disconnect(btn,SIGNAL(clicked()),this,SLOT(close()));
}

Dialog::~Dialog()
{
    delete btn;
}

2. 自带信号→自定义槽函数

信号函数需要查阅文档找出,槽函数需要自己编写。

槽函数是一种特殊的成员函数,只需要在声明的时候加上slots关键字即可。

【例子】点击按钮,移动窗口并打印出窗口当前的坐标。

发射者:按钮对象

信号函数:clicked

接收者:自定义窗口类对象

槽函数:自定义槽函数

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>
#include <QDebug>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton *btn;

// 私有槽函数声明
private slots:
    void mySlot();
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(200,200);
    btn = new QPushButton("触发",this);
    btn->move(100,100);

    connect(btn,SIGNAL(clicked()),this,SLOT(mySlot()));
}

void Dialog::mySlot()
{
    //先获得当前的坐标
    int x = this->x();
    int y = this->y();
    //右下方
    x += 10;
    y += 10;
    // 移动
    move(x,y);
    qDebug() << x << "," << y;
}

Dialog::~Dialog()
{
    delete btn;
}

3. 自定义信号→自定义槽函数/自带槽函数

信号函数需要自己编写,槽函数自己写和查阅都可以。

注意,信号函数是没有权限的,且只有声明没有定义。

【例子】点击按钮,触发自定义槽函数1,在自定义槽函数1中发射自定义信号;使用自定义信号来触发自定义槽函数2。

点击按钮 → 槽函数1(发射自定义信号)

自定义信号 → 槽函数2

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>
#include <QDebug>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton *btn;

private slots:
    // 槽函数1
    void mySlot1();
    void mySlot2();

    // 自定义信号函数
signals:
    void mySignal();
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    btn = new QPushButton("发射自定义信号",this);
    btn->move(200,200);

    // 点击按钮,发射自定义信号
    connect(btn,SIGNAL(clicked()),this,SLOT(mySlot1()));
    connect(this,SIGNAL(mySignal()),this,SLOT(mySlot2()));
}

void Dialog::mySlot1()
{
    // 发射自定义信号
    emit mySignal();
}

void Dialog::mySlot2()
{
    qDebug() << "收到了自定义信号!";
}

Dialog::~Dialog()
{
    delete btn;
}

信号槽传参

信号槽除了基础的通信功能外,还可以携带数据进行传递。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton *btn;

private slots:
    // 自定义槽函数1
    void mySlot1();
    // 自定义槽函数2:接收int参数
    void mySlot2(int);

signals:
    // 参数是携带的数据,可以发射给槽函数
    void mySignal(int);
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(400,400);
    btn = new QPushButton("0",this);
    connect(btn,SIGNAL(clicked()),this,SLOT(mySlot1()));
    connect(this,SIGNAL(mySignal(int)),this,SLOT(mySlot2(int)));
}

void Dialog::mySlot1()
{
    // 计数
    static int count = 0;
    count++;
    // 把次数通过信号函数发射冲出去
    emit mySignal(count);
}

void Dialog::mySlot2(int count)
{
    // QString QString::number(int n, int base = 10) [static]
    QString text = QString::number(count);
    // 把次数显示在窗口标题上
    setWindowTitle(text);
}

Dialog::~Dialog()
{
    delete btn;
}

注意事项:

1. 可以传递任意多个参数

2. 参数类型必须匹配

3. 信号的参数个数可以大于等于槽函数的参数个数

上述代码如果按照正常的开发写法,可以优化为:

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton *btn;
    int count = 0;

private slots:
    void mySlot();
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(300,300);
    btn = new QPushButton("0",this);
    connect(btn,SIGNAL(clicked()),this,SLOT(mySlot()));
}

void Dialog::mySlot()
{
    setWindowTitle(QString::number(++count));
}

Dialog::~Dialog()
{
    delete btn;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值