Каков наилучший способ передачи пользовательского класса (наследует QObject) в QML? - PullRequest
2 голосов
/ 23 марта 2019

Уже довольно давно, используя Qt для приложений на C ++, я захотел сделать следующий проект с использованием QML. Теперь у меня есть следующий сценарий: Pseudo UML of the projects architecture

  • красный : файлы QML и механизм QML
  • синий : классы C ++

Теперь я хочу иметь возможность вызывать функции C ++ из моих файлов QML ( зеленые стрелки ).

  • Content.qml необходимо прочитать свойства из WifiManager
  • LiveField.qml и GameField.qml необходимо показать / скрыть соответствующие представления C ++

Я использовал C ++ для представлений из-за некоторых тяжелых 3D-вещей, с которыми я не очень хорошо знаком в QML (я использовал только QML для меню пользовательского интерфейса).

Я бы предпочел не создавать классы C ++ из моего кода QML, используя qmlRegisterType, так как мне нужно выполнить некоторую инициализацию в моем коде C ++.

Как лучше всего решить мою проблему?

1 Ответ

1 голос
/ 23 марта 2019

C ++ объекты обычно используются с использованием QQmlContext::setContextProperty. Вы можете найти больше информации о QQmlContext здесь . Это делает любой объект (или значение), который вы помещаете в контекст, широко доступным.

Два слова предостережения:

  • Используйте ваши свойства контекста только в компонентах высокого уровня, а не в повторно используемых, поскольку это создаст прямую зависимость от этих значений
  • Будьте внимательны при загрузке графического интерфейса пользователя после того, как вы установили все свои свойства контекста, чтобы убедиться, что они доступны для вашего пользовательского интерфейса с самого начала.

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();
}

Затем вы можете использовать wifiManager на стороне QML вместе с slots, Q_PROPERTY ies и signals

Чтение Q_PROPERTY

Как и в обычном QML, теперь вы можете связывать и читать свойства вашего объекта.

  • Чтение: var value = wifiManager.value
  • Привязка: someProperty: wifiManager.value

Любая привязка QML будет пересматриваться автоматически при каждом изменении значения, если вы посылаете связанный сигнал NOTIFY. Например:

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()
    }
}
...