Qt信号槽原理详解


信号槽示例:connect(QObject* pSender,SIGNAL(sigGetQString(QString)),QObject* pReceiver,SLOT(sltGetQString(QString)));

1、通过MOC(meta object compiler)进行预处理

struct MetaObject
{
	const char* pSigNames;
	const chra* pSltNames;
};

通过预处理器,将信息提取出来,放置到一个单独的文件中(比如test_object.cpp):
规则很简单,将信号和槽的名字提取出来,放到字符串中。可以有多个信号或槽,按顺序"sig1/nsig2/n"
static const char sig_names[] = “sig1/n”;
static const char slts_names[] = “slot1/n”;
SIGNAL关键字和SLOT关键字包含的内容变成char*
connect(Object *, const char *, Object *, const char *);

2、信号和槽关联

信号和槽之间的关联关系存入到Object中(通过char *字符串关联)

struct Connection
{
	Object* pReceiver;
	int iMethod;
}

class Object
{
public:
	static MetaObject stMeta;
	static connnect(Object *, const char *, Object *, const char *);
private:
	std::multimap<int,Connection> mapConnections;
};

//通过connect函数将信号和槽的对应关系存入mapConnections
void Object::connect(Object * pSender, const char * pSigName, Object * pReceiver, const char *)
{
	//在pSender的pSigNames中查找pSigName所在索引iSigIndex
	//在pReceiver的pSltNames中查找pSigName所在索引iSltIndex
	Connection c = {pReceiver, iSltIndex};
	pSender->mapConnections.insert(std::pair<int, Connection>(iSigIndex, c));
}

3、信号激活

信号通过Object成员函数调用转换最后调用MetaObject中的active函数
class Object
{
public:
    void sigGetQString(QString)
...
};

void Object::sigGetQString(QString)
{
    emit sig1();
}

void Object::sig1()
{
    MetaObject::active(this, iIndex);
}

struct MetaObject
{
    const char * sig_names;
    const char * slts_names;

    static void active(Object * pSender, int idx);
};

void MetaObject::active(Object* pSender, int idx)
{
    //通过pSender中的mapConnections,找到对应的pReceiver和pReceiver中的槽函数索引iSltIndex
    //找到iSltIndex,然后调用pReceiver中的槽函数
    rpReceiver->metacall(iSltIndex);
}

4、槽函数的调用

Object成员函数调用
class Object
{
    void metacall(int idx);
...
};

void Object::metacall(int idx)
{
    switch (idx) {
        case 0:
            slot1();
            break;
        default:
            break;
    };
}

5、DirectConnection和QueuedConnection情况下的处理

首先看Assistant上的说明

Qt::DirectConnection:
The slot is invoked immediately, when the signal is emitted.
Qt::QueuedConnection:
The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.

可以看到DirectConnection时是在信号发射线程里面调用的slot,而QueuedConnection时,是通过事件相应的,在接收信号的线程里面执行的slot。
实现流程可以参考下图:
在这里插入图片描述
在我们使用active()激活信号时,会判断我们的连接方式,当我们使用Qt::QueuedConnection作为连接类型时,槽函数的执行是通过抛出QMetaCallEvent事件,经过Qt的事件循环在接收线程里面调用步骤4中的metacall(),达到异步的效果。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值