从QML(Qt Quick应用程序)调用C++方法

8

我做了一些搜索,但是所有我读到的类似问题都没有提供有效的建议。

我正在使用Qt Creator(并且我对Qt不太熟悉),因此我不确定它在后台做了什么。然而,我正在使用标准的Qt Quick Application项目。

本质上,我想从QML调用一个C++函数,该函数返回一个字符串,并定期替换布局中的一些文本。

这是 main.cpp:

#include <QtGui/QApplication>
#include "qmlapplicationviewer.h"
#include <QDeclarativeContext>


class testClass : public QObject
{
    Q_OBJECT
public:
    Q_INVOKABLE QString gimmeText() {
            return QString("new text");
}
};



Q_DECL_EXPORT int main(int argc, char *argv[])
{
    QScopedPointer<QApplication> app(createApplication(argc, argv));

    QmlApplicationViewer viewer;

    viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
    viewer.setMainQmlFile(QLatin1String("qml/Picenter2/main.qml"));

    testClass t;
    viewer.rootContext()->setContextProperty("testOb", &t);

    viewer.showFullScreen();

    return app->exec();
}

以下是布局的一部分代码(大部分显然与主题无关):

Text {
    id: text1
    x: 105
    y: 156
    color: "#ffffff"
    text: qsTr("text")
    font.pixelSize: 12
    Timer {
        interval: 1000; running: true; repeat: false
        onTriggered: text1.text = testOb.gimmeText();
    }

给出的错误如下:
invalid use of incomplete type 'struct QDeclarativeContext' main.cpp (28)
forward declaration of 'struct QDeclarativeContext' qdeclarativeview.h (60)

编辑:包含QDeclarativeContext后,上述错误消失,出现以下错误:

(.text.startup+0x3e):-1: error: undefined reference to `vtable for testClass'
(.text.startup+0xcf):-1: error: undefined reference to `vtable for testClass'
(.text.startup+0x12b):-1: error: undefined reference to `vtable for testClass'
:-1: error: collect2: ld returned 1 exit status

我没有做过太多的C++编程,所以我对这是什么不是很熟悉。按照类似问题的建议只会给我带来vtable错误或更加难以理解的东西。
真正使我困惑的是,查看头文件,QmlApplicationViewer是从QDeclarativeView派生而来,这正是Qt文档在此处使用的方法,几乎可以实现我想要的功能。感谢任何人提供的建议。

错误信息的意思是编译器知道有一个名为“QDeclarativeContext”的类,但不知道解析函数调用所需的细节(例如)。查找声明该类的头文件并在您的示例中包含该头文件。 - Torsten Robitzki
那是我读到的,所以我把它包含进来了。它只给了我三个“undefined reference to `vtable for testClass”的错误提示。 - Logan
3
好的,缺失的符号源于你自己的 testClass。如果我理解正确的话,Qt附带了一个特殊工具,可以从 Q_OBJECT 和 Q_INVOKABLE 宏创建代码。你应该将这个类移到一个单独的头文件中。听起来有些麻烦,但试一下吧 ;-) - Torsten Robitzki
2
"undefined reference to vtable" 通常意味着您需要重新构建项目(make clean + qmake + make)。 - Dmitry Melnikov
3
只有在运行 moc 应用程序生成带有元数据的头文件时,才能使用 make 命令使其正常工作。将 *.cpp 文件添加到 *.pro 文件中作为头文件可以产生相同的效果(但这是一种不好的方法)。 - Marek R
显示剩余3条评论
2个回答

5

您需要注册您的类,以便在QML中使用它。您可以在主函数中执行此操作。您还必须在QML代码中导入它。您的代码应该像这样:

main.cpp:

#include <QtGui/QApplication>
#include "qmlapplicationviewer.h"
#include <QDeclarativeContext>

#include <QtDeclarative>    // Required for registration


class testClass : public QObject
{
    Q_OBJECT
    public:
    Q_INVOKABLE QString gimmeText() {
            return QString("new text");
    }
};



Q_DECL_EXPORT int main(int argc, char *argv[])
{
    QScopedPointer<QApplication> app(createApplication(argc, argv));

    qmlRegisterType<testClass>("MyCustomQMLObjects", 2, 35, "testClassNameInQML");

    QmlApplicationViewer viewer;

    viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
    viewer.setMainQmlFile(QLatin1String("qml/Picenter2/main.qml"));

    testClass t;
    viewer.rootContext()->setContextProperty("testOb", &t);

    viewer.showFullScreen();

    return app->exec();
}

QML代码:

// ...

import MyCustomQMLObjects 2.35

// ...

property testClassNameInQML testOb

// ...

Text {
    id: text1
    x: 105
    y: 156
    color: "#ffffff"
    text: qsTr("text")
    font.pixelSize: 12
    Timer {
        interval: 1000; running: true; repeat: false
        onTriggered: text1.text = testOb.gimmeText();
    }

// ...

0

我没有使用过qt,也看不出代码中哪里触发了错误。然而,当出现这样的错误时,通常是因为一个类(struct QDeclarativeContext)已经被前向声明,但是却像整个定义已知一样使用(访问成员、声明此类型的变量等)。要解决这个问题,您需要包含具有此类型定义的头文件


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接