关于信号与槽

关于信号与槽

信号和槽的机制是类型安全的:一个信号的签名必须与它的接收槽的签名相匹配。(实际上一个槽的签名可以比它接收的信号的签名少,因为它可以忽略额外的签名。)因为签名是一致的,编译器就可以帮助我们检测类型不匹配。信号和槽是宽松地联系在一起的:一个发射信号的类不用知道也不用注意哪个槽要接收这个信号。Qt的信号和槽的机制可以保证如果你把一个信号和一个槽连接起来,槽会在正确的时间使用信号的参数而被调用。信号和槽可以使用任何数量、任何类型的参数。

建立信号与槽的连接

信号与槽的类必须是QObject的派生类,在类中必须加Q_OBJECT的宏定义。连接信号与槽时调用如下函数:

QObject::connect(&data, SIGNAL(ValueChange(Subject*)), &view, SLOT(Update(Subject* )));

connect                是一个静态函数

data                            是信号类的对象

ValueChange       是定义的信号,其参数与槽的参数必须匹配

view                    是槽类的对象

Update                是定义的槽

SIGNALSLOT             是宏定义,具体的不清楚。

解除已经建立好连接的信号和槽

如果要解除已经建立好连接的信号和槽,可以使用disconnect()函数。

bool QObject::disconnect ( const QObject * sender, const char * signal, 
  const Object * receiver, const char * member )

       这个函数断开发射者中的信号和接收者中的槽函数之间的关联。有以下三种情况:

1、断开某个对象与其它对象的任何连接:

disconnect(object, 0, 0, 0);object->disconnect();

2、断开某个信号与其它任何槽的连接:

disconnect(object, SIGNAL(signal()), 0, 0);object->disconnect(SIGNAL(signal()));

3、断开两个对象之间的任何关联:

    disconnect(object, 0, receiver, 0);object->disconnect(receiver);

信号和槽的注意事项

1)    信号和槽必须是QObject 的派生类的成员函数。

2)    如果使用多重继承,QObject必须是第一父类。

3)    在类声明中必须出现Q_OBJECT语句。

4)    信号和槽的机制是非常有效的,但是它不像“真正的”回调那样快。信号和 槽稍微有些慢,这是因为它们所提供的灵活性。

5)    信号和槽机制与普通函数的调用一样,如果使用不当的话,在程序执行时有 可能形成死循环,所以,在定义槽函数时一定要注意避免间接形成无限循环,   即在槽中再次发射所接收到的同样的信号

6)    信号可以和多个槽相关联的话,那当这个信号被发射时,与之相关联的槽的 执行顺序将是随机的,且顺序不能指定

7)    信号也可以与另外一个信号连接。

8)    宏定义不能用在signalslot的参数中

9)    信号不能用于模板。

10)  信号和槽的参数不能是函数指针。

11)  信号和槽不能有缺省参数值

12)  友元声明不能位于信号和槽的声明区域内

13)  信号和槽不能被重定义。


代码示例

产生信号的类:

#ifndef SUBJECT_H

#define SUBJECT_H

#include <QObject>

#include <string>

using namespace std;

class Subject : public QObject /*与信号和槽相关的类必须从此类派生*/

{

Q_OBJECT        //声明

public:

    Subject(QObject * parent = 0);// QObject类的构造函数可以有个参数parent

    virtual ~Subject();

    void SetState(string state);

    string  GetState();

signals:                                                          /*标记开始声明信号*/

    void  ValueChange(Subject* sub);      /*声明一个信号*/

private:

    string m_state;

};

#endif // SUBJECT_H

SUBJECT源文件:

#include <string>

#include "Subject.h"

Subject::Subject(QObject * parent /*= 0*/)

    :QObject(parent)       /*父类的构造函数*/

{

    m_state = "";

}

Subject::~Subject()

{}

void Subject::SetState(string state)

{

    if ( m_state != state)

    {

        m_state = state;

        emit ValueChange(this);

    }

}

string Subject::GetState()

{

    return m_state;

}

 

槽相关类:

#ifndef OBSERVER_H

#define OBSERVER_H

#include <QObject>

#include "Subject.h"

class Observer:public QObject

{

Q_OBJECT

public:

    Observer(QObject * parent = 0);

    ~Observer();

    virtual void PrintInfo(Subject* sub);

public slots:  /**标记开始声明槽/

    void Update(Subject* sub);/*声明一个槽,就是一个函数*/

};

#endif // OBSERVER_H

OBSERVER实现源文件:

#include <iostream>

#include "Observer.h"

Observer::Observer(QObject * parent /*= 0*/)

    :QObject(parent)

{}

Observer::~Observer()

{}

void Observer::PrintInfo(Subject* sub)

{

    string state;

    state = sub->GetState();

    cout<<" state = "<< state<<endl;

}

void Observer::Update(Subject* sub)

{

    this->PrintInfo(sub);

}

最后在主函数中建立信号与槽的连接

#include <QtCore/QCoreApplication>

#include <QObject>

#include "Observer.h"

#include "Subject.h"

int main(int argc, char *argv[])

{

    QCoreApplication a(argc, argv);

    Subject     data;

    Observer    view;

    QObject::connect(&data, SIGNAL(ValueChange(Subject*)), &view, SLOT(Update(Subject* )));

    data.SetState("change the value");

    return a.exec();

}

当然,信号与槽的连接可以放在其他任何地方,只要知道对应信号与槽对象的指针。可以放在槽对应类的构造函数,构造时传递一个信号类,然后建立连接。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值