最后调用callFunction() 或者metaCall()

void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv)
{// 这里得到的是QObject的数据,首先判断是否为阻塞设置if (sender->d_func()->blockSig)return;// 得到全局链表QConnectionList * const list = ::connectionList();if (!list)return;QReadLocker locker(&list->lock);void *empty_argv[] = { 0 };if (qt_signal_spy_callback_set.signal_begin_callback != 0) {locker.unlock();qt_signal_spy_callback_set.signal_begin_callback(sender, from_signal_index,argv ? argv : empty_argv);locker.relock();}// 在sender的哈希表中得到sender的连接QConnectionList::Hash::const_iterator it = list->sendersHash.find(sender);const QConnectionList::Hash::const_iterator end = list->sendersHash.constEnd();if (it == end) {if (qt_signal_spy_callback_set.signal_end_callback != 0) {locker.unlock();qt_signal_spy_callback_set.signal_end_callback(sender, from_signal_index);locker.relock();}return;}QThread * const currentThread = QThread::currentThread();const int currentQThreadId = currentThread ? QThreadData::get(currentThread)->id : -1;// 记录sender连接的索引QVarLengthArray<int> connections;for (; it != end && it.key() == sender; ++it) {connections.append(it.value());// 打上使用标记,因为可能是放在队列中list->connections[it.value()].inUse = 1;}for (int i = 0; i < connections.size(); ++i) {const int at = connections.constData()[connections.size() - (i + 1)];QConnectionList * const list = ::connectionList();// 得到连接QConnection &c = list->connections[at];c.inUse = 0;if (!c.receiver || (c.signal < from_signal_index || c.signal > to_signal_index))continue;// 判断是否放到队列中// determine if this connection should be sent immediately or// put into the event queueif ((c.type == Qt::AutoConnection&& (currentQThreadId != sender->d_func()->thread|| c.receiver->d_func()->thread != sender->d_func()->thread))|| (c.type == Qt::QueuedConnection)) {::queued_activate(sender, c, argv);continue;}// 为receiver设置当前发送者const int method = c.method;QObject * const previousSender = c.receiver->d_func()->currentSender;c.receiver->d_func()->currentSender = sender;list->lock.unlock();if (qt_signal_spy_callback_set.slot_begin_callback != 0)qt_signal_spy_callback_set.slot_begin_callback(c.receiver, method, argv ? argv : empty_argv);
#if defined(QT_NO_EXCEPTIONS)c.receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
#elsetry {// 调用receiver的方法c.receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);} catch (...) {list->lock.lockForRead();if (c.receiver)c.receiver->d_func()->currentSender = previousSender;throw;}
#endifif (qt_signal_spy_callback_set.slot_end_callback != 0)qt_signal_spy_callback_set.slot_end_callback(c.receiver, method);list->lock.lockForRead();if (c.receiver)c.receiver->d_func()->currentSender = previousSender;}if (qt_signal_spy_callback_set.signal_end_callback != 0) {locker.unlock();qt_signal_spy_callback_set.signal_end_callback(sender, from_signal_index);locker.relock();}
}void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv)
{int signal_index = signalOffset + local_signal_index;/* 我们所做的第一件事,是快速检查一个 64 位的位蒙版 bit-mask。如果为 0,* 我们就知道没有连接到该信号的东西,可以迅速返回,* 这意味着,发送一个没有与槽连接的信号是相当迅速的。*/if (!sender->d_func()->isSignalConnected(signal_index))return; // nothing connected to these signals, and no spy/* ... 跳过调试信息和 QML 调用,以及一些合理性检查 ... *//* 使用互斥锁,因为 connectionList 中的所有操作都是线程安全的 */QMutexLocker locker(signalSlotLock(sender));/* 获取该信号的 ConnectionList。此处做了一些简化。真实的代码还为列表添加了引用计数和一些合理性检查 */QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists;const QObjectPrivate::ConnectionList *list =&connectionLists->at(signal_index);QObjectPrivate::Connection *c = list->first;if (!c) continue;// 我们需要最后一次检查,确保在信号发出的过程中添加的信号不会在本次发出过程被触发。QObjectPrivate::Connection *last = list->last;/* 遍历槽 */do {if (!c->receiver)continue;QObject * const receiver = c->receiver;const bool receiverInSameThread = QThread::currentThreadId() == receiver->d_func()->threadData->threadId;// 确定该连接应该立即发出,还是放入事件队列if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)|| (c->connectionType == Qt::QueuedConnection)) {/* 从根本上说,就是复制参数,发出事件 */queued_activate(sender, signal_index, c, argv);continue;} else if (c->connectionType == Qt::BlockingQueuedConnection) {/* ... 跳过 ... */continue;}/* 助手结构体,设置 sender()(并且在超出作用域之后重新设回 */QConnectionSenderSwitcher sw;if (receiverInSameThread)sw.switchSender(receiver, sender, signal_index);const QObjectPrivate::StaticMetaCallFunction callFunction = c->callFunction;const int method_relative = c->method_relative;if (c->isSlotObject) {/* ... 跳过 ...  Qt5 风格的指向函数指针的连接 */} else if (callFunction && c->method_offset metaObject()->methodOffset()) {/* 如果存在 callFunction(指向由 moc 生成的 qt_static_metacall 的指针,* 调用该函数。还需要检查已保存的 metodOffset 是否依旧可用* (因为我们可能在析构函数中调用) */locker.unlock(); // 实际调用时不能持有锁callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv);locker.relock();} else {/* 动态对象 */const int method = method_relative + c->method_offset;locker.unlock();metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv);locker.relock();}// 检查该对象是否被槽析构if (connectionLists->orphaned) break;} while (c != last && (c = c->nextConnectionList) != 0);
}

6. Qt 信号与信号槽 (7)-QMetaObject:: activate相关推荐

  1. Qt / Moc 和信号 - 槽解析

    目录 一. MOC 二. moc_test.cpp 分析 三. connect 四. activate 五. 总结 版本 Qt5.12.3 moc_test.cpp 位于可执行文件目录下,其余源代码都 ...

  2. Qt的特性——信号和槽

    Qt的特性--信号和槽 1. Qt的特性 2. 信号和槽 2.1 信号和槽机制概述 2.2 典型应用示例 2.3 信号和槽的关联 2.4 断开关联 2.5 信号和槽的高级应用 1. Qt的特性 Qt在 ...

  3. Qt::ConnectionType(信号与槽的传递方式)

    Qt::AutoConnection 自动连接:(默认值)如果信号在接收者所依附的线程内发射,则等同于直接连接.如果发射信号的线程和接受者所依附的线程不同,则等同于队列连接. Qt::DirectCo ...

  4. Qt for Python 信号和槽的使用详解

    前言 如果要说 Qt 里面的最常听到的词,那么 "信号"(signals)和"槽"(slots)绝对是其中之一了,其功能简单强大,想必每个 Qt 程序员最能理解 ...

  5. qt 关闭窗口的槽函数_勇哥的VC++应用框架学习之QT(1) 信号槽、按钮控件、opencv读取显示图片...

    前言勇哥对于C语言,C++早些年有一些接触,这个系列贴子就记载一下C++应用框架的学习经验. 在写程序时,UI.基础类库.应用程序框架对于vc来讲,只能依靠MFC和QT了. 勇哥对MFC有很强的抵触, ...

  6. QT中信号和信号槽详解

    如何选择QDialogButtonBox的信号与槽 1.UI中设计了一个QDialogButtonBox,按钮为Cancel和Apply: 2.构造函数连接: connect(ui->butto ...

  7. Qt eventFilter实现信号与槽

    对于Qt来说,信号与槽机制是其通信的一大亮点,但是Qt中也提供了其他的方法实现数据间的通信,如invokeMethod反射机制实现通信(https://blog.csdn.net/xx18030637 ...

  8. Qt工作笔记-信号与槽参数匹配问题

    今天,我把Qt3代码转化为Qt5,控件啥的都要换,李主任说了下为什么以前的信号和槽函数参数不匹配!!这句话让我对Qt中的信号与槽进一步有了了解. 下面的这个演示源码是基于这个博客的 https://b ...

  9. [转载]qt信号signal和槽slot机制

    好东西! 原文地址:qt信号signal和槽slot机制作者:fox1987 信号与槽作为QT的核心机制在QT编程中有着广泛的应用,本文介绍了信号与槽的一些基本概念.元对象工具以及在实际使用过程中应注 ...

最新文章

  1. 一个互联网「打工人」的卑微一天
  2. linux——Firewalld与iptables的基本配置
  3. Electrification
  4. pyspark连接mysql
  5. Java与.NET的WebServices相互调用
  6. winmail计算机三级,2016年计算机三级网络技术机考模拟题(1)
  7. poj 1182 食物链(高级的带权并查集)
  8. Java JDBC初步
  9. dbvisivuser连oracle数据库报错没有权限
  10. HIVE 命令行操作和参数指引
  11. 计算机怎么查文件打印记录表,打印机打印文件历史记录如何查看
  12. linuxcan接口测试
  13. Java——事故应急
  14. 码农造“神盘”:互联网人20年买房故事
  15. K8s Kubernetes集群部署
  16. 可区分英文字母:lL、iI、0Oo的系统字体
  17. 淡出动画fadeOut
  18. linux做gpt分区,Linux下的GPT分区
  19. 聚类算法及其模型评估指标【Tsai Tsai】
  20. latex 表格如何精细控制行高,行距,行与行之间的距离

热门文章

  1. 压缩文件拷到服务器损坏,压缩文件导致无法拷贝共享
  2. 宽屏图片轮播html,jQuery实现宽屏图片轮播实例教程
  3. java logfaction_Java调试的变迁:从System.out.println到log4j
  4. qt通过蓝牙控制单片机_ST发布新款STM32WB55单片机,集成蓝牙5和802.15.4协议...
  5. 重新考虑数据中心的冷却方案—水冷却或将再次兴起
  6. html date 设置时间,JavaScript Date(日期)
  7. 在mysql中怎样设置值唯一_mysql怎么设置行值唯一?
  8. easypoi教程_SpringBoot图文教程17—上手就会 RestTemplate 使用指南
  9. 成功解决ValueError: Shape of passed values is (33, 1), indices imply (33, 2)
  10. BigData之matplotlib:爬虫2018年福布斯中国富豪榜进行数据统计分析,大数据告诉你一些不可思议的事情