将自定义类(继承QObject)传递给QML的最佳方法是什么?

时间:2019-03-23 11:01:40

标签: c++ qt qml qt5

使用Qt进行C ++应用程序已经有一段时间了,现在我想使用QML进行下一个项目。 我现在有以下情况: Pseudo UML of the projects architecture

  • red :QML文件和QML引擎
  • blue :C ++类

现在,我希望能够从QML文件(绿色箭头)中调用C ++函数。

  • Content.qml需要从WifiManager读取属性
  • LiveField.qmlGameField.qml需要显示/隐藏相应的C ++视图

我将C ++用于视图,是因为我对QML不太熟悉(我只在界面菜单中使用了QML)。

我不想使用qmlRegisterType在QML代码中创建C ++类,因为我需要在C ++代码中进行一些初始化。

解决我的问题的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

C ++对象通常使用QQmlContext::setContextProperty进行共享。您可以找到有关QQmlContext here的更多信息。这样一来,您放到上下文中的任何对象(或值)就可以广泛使用。

但请注意两个词:

  • 仅在高级组件中使用上下文属性,而不在可重用的组件中使用上下文属性,因为这将直接依赖于这些值
  • 在设置所有上下文属性后,请小心加载GUI,以确保用户界面从一开始就可以访问它们。

C ++方面

#include "wifimanager.h"

// That one is required
#include <QGuiApplication>
#include <QQmlContext>
#include <QQmlApplicationEngine>   

void main() {
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;

    WifiManager wifi;
    engine.rootContext().setContextProperty("wifiManager", &wifi);

    engine.load(QUrl("qrc:/main.qml"));
    return app.exec();
}

然后,您可以在QML一侧使用wifiManager及其slotsQ_PROPERTY ies和signals

读取Q_PROPERTY

与常规QML一样,您现在可以绑定并读取对象的属性。

  • 阅读:var value = wifiManager.value
  • 绑定:someProperty: wifiManager.value

只要您发出关联的NOTIFY信号,只要值更改,任何QML绑定都将自动重新评估。例如:

Q_PROPERTY(QString ssid READ ssid WRITE setSsid NOTIFY ssidChanged)

Text {
    // Calls the READ getter of your Q_PROPERTY
    // Will automatically update whenever the SSID changes
    text: wifiManager.ssid
}

写一个Q_PROPERTY

就像读取值一样简单,您可以通过执行wifiManager.ssid = xxx

对其进行写入
Button {
    text: "Reset SSID"
    onClicked: {
        // Calls the WRITE setter of your Q_PROPERTY
        wifiManager.ssid = ""
    }
}

处理信号

可以使用Connections对象处理信号。与任何QML对象一样,您必须在信号名称前加上on和大写字母。给出onWifiConnected: {}的信号void wifiConnected();

Connections {
    target: wifiManager
    // Handle `wifiConnected` signal
    onWifiConnected: {
        console.log("Connected!")

        // If your `wifiConnected` signal has an argument named `ip`
        // it will be available here under the same name
        console.log("My IP is", ip)
    }
}

呼叫槽

插槽和Q_INVOKABLE可以像javascript中的任何其他功能一样进行访问。因此,您可以致电wifiManager.disconnect()

Button {
    text: "disconnect"
    onClicked: {
        // Calls the `disconnect` slot or Q_INVOKABLE
        wifiManager.disconnect()
    }
}