Как изменить свойства QML элемента из C ++

Обновить

April 2019

Просмотры

35 раз

1

Я пишу небольшой интервал QT (5,12) приложений в C ++, который будет двигаться центром QMap каждой секунды. Я пытаюсь обновить координаты , так что центр будет обновляться, но после отладки, он всегда оставаться таким же (исходное значение). Это моя первая попытка с QML, поэтому я помогаю себе с сильфоном связи, но , видимо , я не делаю что - то правильно.

https://doc.qt.io/qt-5/qtqml-cppintegration-interactqmlfromcpp.html

функция Update вызывается каждый второй по таймеру

#include <QQmlEngine>
#include <QQmlComponent>

void MainWindow::UpdateCoordinates()
{
    float LATDEGM = (60 * 1853.181);
    float DEG2RAD = (PI / 180.0);

    QString speedData = ui->sboxSpeed->text();
    bool ok;
    AirSpeed = speedData.toInt(&ok);
    AirCourse = (AirCourse + 360) % 360;

    Dx = AirSpeed * sin((float)AirCourse * DEG2RAD);
    Dy = AirSpeed * cos((float)AirCourse * DEG2RAD);

    QString dat = ui->txtLatitude->text();
    Lat = dat.toDouble();
    QString dat2 = ui->txtLongtitude->text();
    Lon = dat2.toDouble();

    Dx /= 3.6;
    Dy /= 3.6;

    Lat += Dy / LATDEGM;
    Lon += Dx / (LATDEGM * cos(Lat * DEG2RAD));

    ui->txtLatitude->setText(QString::number(Lat));
    ui->txtLongtitude->setText(QString::number(Lon));

    // Using QQmlComponent
    QQmlEngine engine;
    QQmlComponent component(&engine,QUrl(QStringLiteral("qrc:/Map.qml")));
    QObject *object = component.create();
    QObject *map = object->children().at(1);

    if (map)
    {
        map->setProperty("newLatitude", Lat);
        map->setProperty("newLongitude", Lon);
        std::cout << "Property value:" << map->property("latitude").toDouble() << std::endl;
        std::cout << "Property value:" << map->property("longitude").toDouble() << std::endl;
    }
}

Map.qml

import QtQuick 2.0
import QtQuick.Window 2.0
import QtLocation 5.6
import QtPositioning 5.6

Item{
    id: itemControl
    width: 512
    height: 512
    visible: true

    property alias newLongitude : map.longitude;
    property alias newLatitude : map.latitude;

    Plugin {
        id: mapPlugin
        name: "esri"
    }

    Map {
        id: map
        anchors.fill: parent
        maximumZoomLevel: 15
        minimumZoomLevel: 15
        width: 512
        height: 512
        plugin: mapPlugin
        center {
            property real latitude: 45.5082047
            property real longitude: 13.5757492
        }
        zoomLevel: 14
    }
}

1 ответы

3

By doing this:

    // Using QQuickView
    QQmlEngine engine;
    QQmlComponent component(&engine,QUrl(QStringLiteral("qrc:/Map.qml")));
    QObject *object = component.create();
    QObject *map = object->children().at(1);

You're creating a new local instance of you view. So, you don't modify your current view.

The easiest to send data to your view is to use signals/slots. Or, you can pass a pointer on your component to your MainWindow:

For example:

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    property int foobar: -1
    Label {
        text: foobar
    }
}
class Worker: public QObject
{
public:
    Worker(QObject* map): QObject(),
        map(map)
    {
        startTimer(500);
    }

    void timerEvent(QTimerEvent* ev)
    {
        static int i = 0;
        ++i;
        map->setProperty("foobar", i);
    }
private:
    QObject* map;
};

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QApplication app(argc, argv);
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    QObject* obj = engine.rootObjects().first();

    Worker* worker = new Worker(obj);

    return app.exec();
}

An quick example with signals/slots (useful when the class Worker doesn't have to know the inner component):


ApplicationWindow {
    visible: true
    width: 640
    height: 480

    function update(value) {
        label.text = value;
    }

    Label {
        id: label
        text: "None"
    }
}
class Worker: public QObject
{
    Q_OBJECT
public:
    Worker(): QObject()
    {
        startTimer(500);
    }

    void timerEvent(QTimerEvent* ev)
    {
        static int i = 0;
        ++i;
        emit update(i);
    }

signals:
    void update(QVariant newValue);
};

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QApplication app(argc, argv);
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    QObject* obj = engine.rootObjects().first();

    Worker* worker = new Worker();

    QObject::connect(worker, SIGNAL(update(QVariant)), obj, SLOT(update(QVariant)));
    return app.exec();
}