如何在 C++ 中获取 QML 方法的源代码?
Posted
技术标签:
【中文标题】如何在 C++ 中获取 QML 方法的源代码?【英文标题】:How to get source code of a QML method in C++? 【发布时间】:2014-11-08 03:27:05 【问题描述】:我正在将对象序列化到 QML,并且希望能够获得 QML 对象中定义的函数的源代码。假设我在 QML (test.qml
) 中有以下示例:
import QtQml 2.2
QtObject
function foo()
return 42;
我从中创建了一个QObject
: obj
。
有没有什么方法(可以是hacky)在不解析QML文件obj
创建的情况下获取obj
的方法foo
的源代码?
可以使用QQmlComponent
obj
是从或任何其他Qt 类创建的,只要我不必自己解析即可。或者,如何在不编写我自己的解析器的情况下从test.qml
文件中获取函数的源代码?我不想假设 test.qml
有什么特别之处(例如,它可以与上面的不同,它不必简单到可以使用正则表达式或其他不成熟的 QML 解析器)。
假设它像 javascript 一样工作,我尝试了类似的东西:
QQmlExpression expr(engine.rootContext(), obj, "foo.toString()");
QVariant sourceCode = expr.evaluate();
但是,它不起作用。
编辑:根据http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.2,函数对象原型的toString
方法是实现定义的。如果是 QML,我会得到结果:
QVariant(QString, "function() [code] ")
由于似乎没有办法通过 JS 或 C++ 获取代码,因此我不再将自己局限于公共 Qt API。
【问题讨论】:
您想要源代码?还是只想运行函数? 我需要源代码,而不是运行函数。 【参考方案1】:我认为从已经创建的 QML 对象中获取函数的源代码是不可能的。它似乎没有任何 C++ 接口,JavaScript 也没有使用 toSource
方法返回它。
但是,可以使用 QML 解析器来检索它。坏消息是 QML 解析器是 Qt 私有 API 的一部分,因此在使用不同的 Qt 库构建时它可能无法正常工作。
使用 Qt 5.3.0 私有 API 解析 QML 的代码或多或少:
.pro
文件:
QT += qml qml-private
cpp
文件:
using namespace QQmlJS::AST;
class LVisitor: public QQmlJS::AST::Visitor
public:
LVisitor(QString code): _code(code)
virtual bool visit(FunctionBody *fb)
qDebug() << "Visiting FunctionBody" <<
printable(fb->firstSourceLocation(), fb->lastSourceLocation());
return true;
private:
QStringRef printable(const SourceLocation &start, const SourceLocation &end)
return QStringRef(&_code, start.offset, end.offset + end.length - start.offset);
private:
QString _code;
;
void testQmlParser()
QFile file(":/test.qml");
file.open(QFile::ReadOnly);
QString code = file.readAll();
file.close();
QQmlJS::Engine engine;
QQmlJS::Lexer lexer(&engine);
lexer.setCode(code, 1, true);
QQmlJS::Parser parser(&engine);
if (!parser.parse() || !parser.diagnosticMessages().isEmpty())
foreach (const QQmlJS::DiagnosticMessage &m, parser.diagnosticMessages())
qDebug() << "Parse" << (m.isWarning() ? "warning" : "error") << m.message;
UiProgram *ast = parser.ast();
LVisitor visitor(code);
ast->accept(&visitor);
要获取有关定义函数的对象的更精确信息或只是从 AST 获取更多信息,请实现更多 QQmlJS::AST::Visitor
方法。
【讨论】:
【参考方案2】:我也没有找到任何方法。但我找到了解决办法。
reffer this 优先
现在,如您所知,我们可以在 C++ 中访问 QML 对象。将执行以下操作以在 QML 中运行该函数。
Item
width: 100; height: 100
Rectangle
property bool call:true
objectName: "rect"
onCallChanged()
myFunction();
function myFunction()
//your code
在 C++ 中,您必须执行以下操作:
QObject *rect = object->findChild<QObject*>("rect");
if (rect)
rect->setProperty("call", !(rect->property("call").toBool()));
这里我们使用属性'call'的更改事件来调用myFunction()
【讨论】:
我需要源代码,而不是运行函数的方法。此外,要运行我提供的 sn-p 功能就可以了:QQmlExpression expr(engine.rootContext(), obj, "foo()");
.以上是关于如何在 C++ 中获取 QML 方法的源代码?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Blackberry Cascades、QML 和 C++、QT 的列表视图中获取 Web 视图
如何在 C++ 代码中的一些“繁重”操作之前使 QML 对象可见