Qt信号和槽的使用和核心源码分析

最近几天研究了一下信号和槽,总结一下。直接上干货,少写千篇一律的内容。

Qt的信号和槽是解决两个以及多个QObject对象通信的问题,拿A B C三个对象举例,A对象可以自定义信号并且发出信号,B和C对象可以作为观察者监听A的信号。A对象发出信号的时候,B和C的槽函数会被调用。
其中关键的函数是QObject::connect函数和关键字emit。

  • connect函数
    connect函数负责生成被观察者和观察者的连接信息,这些连接信息可以是一对多的,多对多的,多对一的。具体执行的时机是在信号发射的时候。
QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal,
                                     const QObject *receiver, const char *method,
                                     Qt::ConnectionType type)
  • Qt::ConnectionType
    connect函数的最后一个参数是指定信号和槽的连接方式:
    Qt::DirectConnection: 相当于函数的直接调用
    Qt::QueuedConnection: 异步调用
    Qt::AutoConnection: 如果发送者在emit的时候所在的线程等于接受者所依附的线程,则为同步调用,否则为上面的异步调用方式
    Qt::BlockingQueuedConnection:同步调用
    Qt::UniqueConnection:单一连接
  • emit
    emit是核心,把信号和什么槽进行连接以及以什么方式连接进行处理,我们要重点关注这个函数。在qt里,emit其实为空(看下面的宏定义)
# define emit

写上emit是为了保持代码的可读性,如果不写也没问题,但是建议写上,一份好的代码肯定是便于阅读的。比如声明的信号 signal_fun,用过Qt的都知道,我们在代码里是不用实现signal_fun这个函数的,原因是因为Qt为了实现信号与槽,引入了元对象系统,moc编译器会实现这些函数。实际上在emit的时候会调用下面的函数:

void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv)
{
   
    int signal_index = signalOffset + local_signal_index;

	//发送者阻塞标志位true,不执行槽函数,直接返回
    if (sender->d_func()->blockSig)
        return;

    Q_TRACE_SCOPE(QMetaObject_activate, sender, signal_index);

    if (sender->d_func()->isDeclarativeSignalConnected(signal_index)
            && QAbstractDeclarativeData::signalEmitted) {
   
        Q_TRACE_SCOPE(QMetaObject_activate_declarative_signal, sender, signal_index);
        QAbstractDeclarativeData::signalEmitted(sender->d_func()->declarativeData, sender,
                                                signal_index, argv);
    }

    if (!sender->d_func()->isSignalConnected(signal_index, /*checkDeclarative =*/ false)
        && !qt_signal_spy_callback_set.signal_begin_callback
        && !qt_signal_spy_callback_set.signal_end_callback) {
   
        // The possible declarative connection is done, and nothing else is connected, so:
        return;
    }

    void *empty_argv[] = {
    0 };
    if (qt_signal_spy_callback_set.signal_begin_callback != 0) {
   
        qt_signal_spy_callback_set.signal_begin_callback(sender, signal_index,
                                                         argv ? argv : empty_argv);
    }

    {
   
    QMutexLocker locker(signalSlotLock(sender));
    struct ConnectionListsRef {
   
        QObjectConnectionListVector *connectionLists;
        ConnectionListsRef(QObjectConnectionListVector *connectionLists) : connectionLists(connectionLists)
        {
   
            if (connectionLists)
                ++connectionLists->inUse;
        }
        ~ConnectionListsRef(
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值