QT<三> 信号和槽机制

一、信号和槽机制

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

1、连接函数

  QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)
  //QT4版本 缺点类型不做检测
 QObject::connect(scrollBar, SIGNAL(valueChanged(int value)),
                   label, SLOT(setNum(int value)));
  • sender:发出信号的对象
  • signal:发出的信号
  • receiver:接收信号的对象
  • method:接收对象在接收到信号之后所需要调用的函数(槽函数)

2、示例

//关闭当前窗口的按钮
	QPushButton *btn = new QPushButoon("close",this);
	connect(btn, &QPushButton::clicked, this, &QWidget::close);

clicked()是系统自带的信号,即鼠标点击。此外还有pressed(),鼠标按下,released()鼠标释放等。

3、自定义信号和槽

使用connect()可以让我们连接系统提供的信号和槽。但是,Qt 的信号槽机制并不仅仅是使用系统提供的那部分,还会允许我们自己设计自己的信号和槽。

  1. 自定义信号

    写到signals下,返回值为void。需要声明不需要实现,可以有参数,可以重载。示例如下:

#include <QObject>
class Teacher : public QObject
{
    Q_OBJECT
public:
    explicit Teacher(QObject *parent = nullptr){};

signals:
    void Hungry();//自定义的信号函数
public slots:
};
  1. 自定义槽函数

    写到 public slot下 或者public 或者全局函数(需要高版本)。返回值为void。需要声明且需要实现,可以有参数,可以重载。示例如下:

#include <QObject>
class Student : public QObject
{
    Q_OBJECT
public:
    explicit Student(QObject *parent = nullptr){};

signals:

public slots:
    void Treat();//自定义的槽函数
};

void Student::Treat()
{
    qDebug()<< "请老师吃饭";
}

  1. 触发自定义信号

    使用 emit 在恰当的位置发送信号。

{
 	Teacher *tc;
    Student *st;
    //创建老师和学生对象
    tc = new(std::nothrow) Teacher(this);
    st = new(std::nothrow) Student(this);
    //老师饿了 学生请客 连接
    connect(tc, &Teacher::Hungry, st, &Student::Treat);
    //下课函数
    classIsOver();
}
void Widget::classIsOver()
{//下课后函数 触发调用老师饿了信号
    emit tc->Hungry();//触发信号
}
  1. 当自定义信号和槽出现重载

    需要利用函数指针,明确指向函数的地址。

//Teacher
	void Hungry(QString foodName);
//Student
	void Student::Treat(QString foodName)
	{
	    qDebug()<<"请老师吃饭,吃"<<foodName.toUtf8().data();
	}

    //连接带参数的信号和槽
    void(Teacher:: *teacherSignal)(QString) = &Teacher::Hungry;
    void(Student:: *studentSlot) (QString) = &Student::Treat;
    connect(tc,teacherSignal,st,studentSlot);
    classIsOver();
  • 槽函数是普通的成员函数,作为成员函数,会受到 public、private、protected 的影响;
  • 任何成员函数、static 函数、全局函数和 Lambda 表达式都可以作为槽函数
  • 信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致
  • 如果信号和槽的参数不一致,允许的情况是,槽函数的参数可以比信号的少,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。

4、信号槽的拓展

  • 一个信号可以和多个槽相连 如果是这种情况,这些槽会一个接一个的被调用,但是它们的调用顺序是不确定的。

  • 多个信号可以连接到一个槽 只要任意一个信号发出,这个槽就会被调用。

  • 一个信号可以连接到另外的一个信号 当第一个信号发出时,第二个信号被发出。除此之外,这种信号-信号的形式和信号-槽的形式没有什么区别。

    //点击下课按钮之后在下课   --信号连接信号
    QPushButton* btn = new(std::nothrow) QPushButton("下课",this);
    btn->resize(60,50);
    btn->move(270,400);
    //点击按钮下课
 //   connect(btn,&QPushButton::clicked,this,&Widget::classIsOver);

//连接无参数的信号和槽
    void(Teacher:: *teacherSignal2)(void) = &Teacher::Hungry;
    void(Student:: *studentSlot2) (void) = &Student::Treat;
    connect(tc,teacherSignal2,st,studentSlot2);
//信号连接信号
    connect(btn,&QPushButton::clicked,tc,teacherSignal2);
  • 槽可以被取消链接 这种情况并不经常出现,因为当一个对象delete之后,Qt自动取消所有连接到这个对象上面的槽。

  • 信号槽可以断开 利用disconnect关键字是可以断开信号槽的

//断开信号
    disconnect(tc,teacherSignal2,st,studentSlot2);
  • 使用Lambda 表达式
    在使用 Qt 5 的时候,能够支持 Qt 5 的编译器都是支持 Lambda 表达式的。
    在连接信号和槽的时候,槽函数可以使用Lambda表达式的方式进行处理。

5、总结
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值