6. Qt 信号与信号槽 (7)-QMetaObject:: activate
最后调用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相关推荐
- Qt / Moc 和信号 - 槽解析
目录 一. MOC 二. moc_test.cpp 分析 三. connect 四. activate 五. 总结 版本 Qt5.12.3 moc_test.cpp 位于可执行文件目录下,其余源代码都 ...
- Qt的特性——信号和槽
Qt的特性--信号和槽 1. Qt的特性 2. 信号和槽 2.1 信号和槽机制概述 2.2 典型应用示例 2.3 信号和槽的关联 2.4 断开关联 2.5 信号和槽的高级应用 1. Qt的特性 Qt在 ...
- Qt::ConnectionType(信号与槽的传递方式)
Qt::AutoConnection 自动连接:(默认值)如果信号在接收者所依附的线程内发射,则等同于直接连接.如果发射信号的线程和接受者所依附的线程不同,则等同于队列连接. Qt::DirectCo ...
- Qt for Python 信号和槽的使用详解
前言 如果要说 Qt 里面的最常听到的词,那么 "信号"(signals)和"槽"(slots)绝对是其中之一了,其功能简单强大,想必每个 Qt 程序员最能理解 ...
- qt 关闭窗口的槽函数_勇哥的VC++应用框架学习之QT(1) 信号槽、按钮控件、opencv读取显示图片...
前言勇哥对于C语言,C++早些年有一些接触,这个系列贴子就记载一下C++应用框架的学习经验. 在写程序时,UI.基础类库.应用程序框架对于vc来讲,只能依靠MFC和QT了. 勇哥对MFC有很强的抵触, ...
- QT中信号和信号槽详解
如何选择QDialogButtonBox的信号与槽 1.UI中设计了一个QDialogButtonBox,按钮为Cancel和Apply: 2.构造函数连接: connect(ui->butto ...
- Qt eventFilter实现信号与槽
对于Qt来说,信号与槽机制是其通信的一大亮点,但是Qt中也提供了其他的方法实现数据间的通信,如invokeMethod反射机制实现通信(https://blog.csdn.net/xx18030637 ...
- Qt工作笔记-信号与槽参数匹配问题
今天,我把Qt3代码转化为Qt5,控件啥的都要换,李主任说了下为什么以前的信号和槽函数参数不匹配!!这句话让我对Qt中的信号与槽进一步有了了解. 下面的这个演示源码是基于这个博客的 https://b ...
- [转载]qt信号signal和槽slot机制
好东西! 原文地址:qt信号signal和槽slot机制作者:fox1987 信号与槽作为QT的核心机制在QT编程中有着广泛的应用,本文介绍了信号与槽的一些基本概念.元对象工具以及在实际使用过程中应注 ...
最新文章
- 一个互联网「打工人」的卑微一天
- linux——Firewalld与iptables的基本配置
- Electrification
- pyspark连接mysql
- Java与.NET的WebServices相互调用
- winmail计算机三级,2016年计算机三级网络技术机考模拟题(1)
- poj 1182 食物链(高级的带权并查集)
- Java JDBC初步
- dbvisivuser连oracle数据库报错没有权限
- HIVE 命令行操作和参数指引
- 计算机怎么查文件打印记录表,打印机打印文件历史记录如何查看
- linuxcan接口测试
- Java——事故应急
- 码农造“神盘”:互联网人20年买房故事
- K8s Kubernetes集群部署
- 可区分英文字母:lL、iI、0Oo的系统字体
- 淡出动画fadeOut
- linux做gpt分区,Linux下的GPT分区
- 聚类算法及其模型评估指标【Tsai Tsai】
- latex 表格如何精细控制行高,行距,行与行之间的距离
热门文章
- 压缩文件拷到服务器损坏,压缩文件导致无法拷贝共享
- 宽屏图片轮播html,jQuery实现宽屏图片轮播实例教程
- java logfaction_Java调试的变迁:从System.out.println到log4j
- qt通过蓝牙控制单片机_ST发布新款STM32WB55单片机,集成蓝牙5和802.15.4协议...
- 重新考虑数据中心的冷却方案—水冷却或将再次兴起
- html date 设置时间,JavaScript Date(日期)
- 在mysql中怎样设置值唯一_mysql怎么设置行值唯一?
- easypoi教程_SpringBoot图文教程17—上手就会 RestTemplate 使用指南
- 成功解决ValueError: Shape of passed values is (33, 1), indices imply (33, 2)
- BigData之matplotlib:爬虫2018年福布斯中国富豪榜进行数据统计分析,大数据告诉你一些不可思议的事情