QMetaObject之invokeMethod说明和使用
来源:互联网 发布:jq 将数组导出excel 编辑:程序博客网 时间:2024/05/01 09:38
QMetaObject之invokeMethod 点滴记录(有时间在看看)
分类: QT编程
qtsemaphoreconstructorobjectsignalfunction
目录(?)[+]
QMetaObject之invokeMethod 点滴记录
2010-10-18 16:53
起源
C++ GUI Qt4 编程 一书多线程部分提到invokeMethod的用法
QMetaObject::invokeMethod(label, SLOT(setText(const QString&)), Q_ARG(QString, "Hello"));
而 Qt Manual 中介绍却是
- You only need to pass the name of the signal or slot to this function, not the entire signature. For example, to asynchronously invoke the animateClick() slot on a QPushButton, use the following code:
QMetaObject::invokeMethod(pushButton, "animateClick");
这可怎么办?一个是官方的图书,一个是官方的Manual。是否意味着两种方式都可以呢,还是说Qt的早期版本用的是前者?
查 Qt4.7/Qt4.6/Qt4.5/Qt4.4/Qt4.3/Qt4.2/Qt4.1/Qt4.0 ,结果发现都没有提到前面的用法。是不是书的出错呢?网上搜一下:确实有人抱怨它不工作
测试
本着事实就是的精神,还是先写个程序测试一下:
#include <QtCore/QObject> #include <QtCore/QDebug> #include <QtCore/QCoreApplication> class Test : public QObject { Q_OBJECT public: Test(QObject * parent):QObject(parent) { connect(this, SIGNAL(sig1(QString)), SLOT(slot1(QString))); QMetaObject::invokeMethod(this, "sig1", Q_ARG(QString, "constructor")); } Q_INVOKABLE void method1(const QString& t) { qDebug()<<"from method:"<<t; } signals: void sig1(const QString& t); public slots: void slot1(const QString& t) { qDebug()<<"from slot:"<<t; } }; #include "main.moc" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Test obj(0); QMetaObject::invokeMethod(&obj, "slot1", Q_ARG(QString, "Hello")); QMetaObject::invokeMethod(&obj, "method1", Q_ARG(QString, "Hello")); QMetaObject::invokeMethod(&obj, SLOT(slot1(QString)), Q_ARG(QString, "Hello with SLOT")); QMetaObject::invokeMethod(&obj, METHOD(method1(QString)), Q_ARG(QString, "Hello with METHOD")); return a.exec(); }
确实如他人所说,SLOT这种用法不工作
from slot: "constructor" from slot: "Hello" from method: "Hello" QMetaObject::invokeMethod: No such method Test::1slot1(QString)(QString) QMetaObject::invokeMethod: No such method Test::0method1(QString)(QString)
源码
顺便看看源码吧
bool QMetaObject::invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0, QGenericArgument val1, QGenericArgument val2, QGenericArgument val3, QGenericArgument val4, QGenericArgument val5, QGenericArgument val6, QGenericArgument val7, QGenericArgument val8, QGenericArgument val9) { if (!obj) return false; QVarLengthArray<char, 512> sig; int len = qstrlen(member); if (len <= 0) return false;
生成函数原型字符串(从这儿可以看到书中方法不工作的原因)
sig.append(member, len); sig.append('('); const char *typeNames[] = {ret.name(), val0.name(), val1.name(), val2.name(), val3.name(), val4.name(), val5.name(), val6.name(), val7.name(), val8.name(), val9.name()}; int paramCount; for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) { len = qstrlen(typeNames[paramCount]); if (len <= 0) break; sig.append(typeNames[paramCount], len); sig.append(','); } if (paramCount == 1) sig.append(')'); // no parameters else sig[sig.size() - 1] = ')'; sig.append('\0');
在元对象系统中看该函数信息是否存在
int idx = obj->metaObject()->indexOfMethod(sig.constData()); if (idx < 0) { QByteArray norm = QMetaObject::normalizedSignature(sig.constData()); idx = obj->metaObject()->indexOfMethod(norm.constData()); } if (idx < 0 || idx >= obj->metaObject()->methodCount()) { qWarning("QMetaObject::invokeMethod: No such method %s::%s", obj->metaObject()->className(), sig.constData()); return false; }
获得相应的 QMetaMethod,调用其 invoke 方法
QMetaMethod method = obj->metaObject()->method(idx); return method.invoke(obj, type, ret, val0, val1, val2, val3, val4, val5, val6, val7, val8, val9); }
QMetaMethod::invoke
接着看看它的源码,首先:
* 如果指定了返回值,检查返回值的类型是否和QMetaMethod 的中的一致
if (returnValue.data()) { const char *retType = typeName(); if (qstrcmp(returnValue.name(), retType) != 0) { // normalize the return value as well // the trick here is to make a function signature out of the return type // so that we can call normalizedSignature() and avoid duplicating code QByteArray unnormalized; int len = qstrlen(returnValue.name()); unnormalized.reserve(len + 3); unnormalized = "_("; // the function is called "_" unnormalized.append(returnValue.name()); unnormalized.append(')'); QByteArray normalized = QMetaObject::normalizedSignature(unnormalized.constData()); normalized.truncate(normalized.length() - 1); // drop the ending ')' if (qstrcmp(normalized.constData() + 2, retType) != 0) return false; } }
为了利用现有的代码来规范化这儿返回值的类型,这儿构造了一个函数_(typeOfReturn)。
* 检查参数个数,传递的参数是否不少于需要的参数
* 检查Connection的类型,处理AutoConnection
// check connection type QThread *currentThread = QThread::currentThread(); QThread *objectThread = object->thread(); if (connectionType == Qt::AutoConnection) { connectionType = currentThread == objectThread ? Qt::DirectConnection : Qt::QueuedConnection; }
- 对于 直连的,直接调 metacall,它进而去调用对象的 qt_metacall
if (connectionType == Qt::DirectConnection) { return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, methodIndex, param) < 0;
- 对于 Queued 的连接,post 相应的事件,进而转到对象的event()函数中
if (connectionType == Qt::QueuedConnection) { QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex, 0, -1, nargs, types, args));
- 对于 bolckedqueued 的连接,使用了信号量
QSemaphore semaphore; QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex, 0, -1, nargs, types, args, &semaphore)); semaphore.acquire();
0 0
- QMetaObject之invokeMethod说明和使用
- QMetaObject之invokeMethod 点滴记录
- QMetaObject::invokeMethod and Q_INVOKABLE
- QMetaObject之invokeMethod 点滴记录(有时间在看看)
- qml之invokeMethod的使用
- Qt多线程 信号和槽以及C++11的绑定 及QMetaObject::invokeMethod
- QMetaObject::invokeMethod: No such method的问题
- QMetaObject使用
- QMetaObject::invokeMethod()---------Qt 类外调用一个 private slots 函数
- Groovy探索之MOP 一 invokeMethod和methodMissing方法
- Groovy探索之invokeMethod方法
- Qt 源码之元对象(QMetaObject)
- QtMetaObjectsysmtem详解之三:QMetaObject接口实现
- Groovy探索之MOP 十一 运行期内覆盖invokeMethod
- Qt函数connectSlotsByName(),即"QMetaObject::connectSlotsByName(QObject *o)"的说明
- 跨线程更新空间的值,使用invokeMethod.
- Subversion配置和使用之服务器端配置说明(2)
- Subversion配置和使用之服务器端配置说明(2)
- java web与discuz社区整合(二)
- 【读书笔记:C++ primer plus 第六版 中文版】第17章 输入、输出和文件
- PHP+MySQL开发的10条建议
- Java中Excel的导入导出
- 使用lsnrctl status命令区分动态注册,静态注册
- QMetaObject之invokeMethod说明和使用
- 内存管理单元(MMU)介绍
- spring web常用包的版本(gradle.properties)
- 2015优秀的前端框架介绍
- source insight 注册码
- Asp.net 中高亮显示搜索关键字简单方法
- 费式数列:兔子问题
- Android自绘字体大小paint.settextsize随分辨率大小变化
- 如何成为程序员高手(转)