如何在 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 对象可见

Qt Quick - 如何仅通过 c++ 代码与 qml 属性交互

QML:在 C++ 中获取 MouseArea 的鼠标事件

QML TextField输入的文本传输到C++

如何从 C++ 访问特定 QML 控件的事件