简体   繁体   English

使用来自 C++ 的信号更新 QML 上的 MapCircle

[英]Update a MapCircle on QML using a signal from C++

I'm trying to update a MapCircle in QML from a signal in C++ and I'm veen having several issues with it all day.我正在尝试从 C++ 中的信号更新 QML 中的 MapCircle,我整天都遇到几个问题。

In my class I have a Q_PROPERTY which is read only and holds the GPS positions of 4 UAVs in a QVariantList在我的 class 中,我有一个Q_PROPERTY ,它是只读的,并且在QVariantList中保存 4 个 UAV 的 GPS 位置

class GCS: public QObject
{
    Q_PROPERTY(QVariantList getUavPosition READ getUavPosition NOTIFY uavPositionSet)

    public:
      QVariantList getUavPosition() ; 
    signals:
      void uavPositionSet();
     public slots:
       void setUavPosition();
       void triggerPosition();
     private: 
       QVariantList connected_uavs;
       QVector<QGeoCoordinate> uav_positions;         

};

I then define the functions as:然后我将函数定义为:

void GCS::setUavPosition()
{
  double i = 0.0;

     QGeoCoordinate uav_id;
     uav_id.setLatitude(0.5);
     uav_id.setLongitude(0.5 + i);
     uav_id.setAltitude(5);
     uav_positions.insert(0, uav_id);
     connected_uavs.append( QVariant::fromValue(QGeoCoordinate(uav_positions[0].latitude(), uav_positions[0].longitude())));

      i+=0.15;  
    emit uavPositionSet();

}

 QVariantList GCS::getUavPosition() 
 {
   return connected_uavs;
 }

void GCS::triggerPosition()
{
  setUavPosition();
  ROS_INFO("Pos trig");
}

In my main function, I connect triggerPosition to a Timer so as to update the position periodically在我的主要 function 中,我将triggerPosition连接到 Timer 以便定期更新 position

int main(int argc, char *argv[])
{
     ros::init(argc, argv, "planner");
    QGuiApplication app(argc, argv);

     QQmlApplicationEngine engine;
     QQmlContext* context = engine.rootContext();
     GCS gcs;
     context->setContextProperty("planner", &gcs);    
     engine.load(QUrl(QStringLiteral("qrc:/planner.qml")));

     QTimer *timer = new QTimer();
     timer->setInterval(1000);
     QObject::connect(&gcs, SIGNAL(uavPositionSet()), &gcs, SLOT(setUavPosition()));
     QObject::connect(timer, SIGNAL(timeout()), &gcs, SLOT(triggerPosition()));
     timer->start();

    return app.exec();
}

However, when I run my program, there's a slight delay, my mouseArea becomes unusable and the program crashes.但是,当我运行我的程序时,会有一点延迟,我的mouseArea变得不可用并且程序崩溃了。 When I try to print the longitude to see if it updates, The initial value is printed out multiple times to the terminal but then the program crashes and there's is no MapCircle present on the map当我尝试打印经度以查看它是否更新时,初始值被多次打印到终端,但随后程序崩溃并且 map 上没有MapCircle

The relevant part of My Qml file looks like this:我的 Qml 文件的相关部分如下所示:

 Map{
        id: map
        anchors.fill:parent
        plugin: mapPlugin
        center: QtPositioning.coordinate(0.5, 0.5)
        zoomLevel:50

        MapCircle{
            id:uavPos
            radius:2
            color:'black'
            border.width:3   
        }

    Connections{
        id:uavConnection
        target: planner
        onUavPositionSet:{

        var data = planner.getUavPosition
        uavPos.center = QtPositioning.coordinate(data[0].latitude, data[0].longitude)
        console.log(data[0].longitude)
        }

        }

    }

Can someone please kindly point me in the right direction here?有人可以在这里指出我正确的方向吗?

If you are going to handle information from several elements then it is better to use a model (together with a Repeater to create several elements), so it is only necessary to modify the role of an item:如果您要处理来自多个元素的信息,那么最好使用 model(与中继器一起创建多个元素),因此只需修改一个项目的角色:

gcs.h gcs.h

#ifndef GCS_H
#define GCS_H

#include <QObject>

class QStandardItemModel;
class QAbstractItemModel;

class GCS: public QObject
{
    Q_OBJECT
    Q_PROPERTY(QObject* uavModel READ uavModel CONSTANT)
public:
    enum UAVRoles {
        PositionRole = Qt::UserRole + 1000
    };
    GCS(QObject *parent=nullptr);
    QObject *uavModel() const;
public Q_SLOTS:
    void triggerPosition();
private:
    QStandardItemModel* m_uavModel;
};

#endif // GCS_H

gcs.cpp gcs.cpp

#include "gcs.h"

#include <QGeoCoordinate>
#include <QStandardItemModel>

#include <random>

GCS::GCS(QObject *parent):
    QObject(parent), m_uavModel(new QStandardItemModel(this))
{
    m_uavModel->setItemRoleNames({{PositionRole, "position"}});
    for(int i =0; i < 4; i++){
        QStandardItem *item = new QStandardItem;
        item->setData(QVariant::fromValue(QGeoCoordinate()), PositionRole);
        m_uavModel->appendRow(item);
    }
}

QObject *GCS::uavModel() const{
    return m_uavModel;
}

void GCS::triggerPosition(){
    std::mt19937 rng;
    rng.seed(std::random_device()());
    std::normal_distribution<> dist(-0.0001, +0.0001);

    if(QStandardItem *item = m_uavModel->item(0)){
        QGeoCoordinate uav_id;
        uav_id.setLatitude(0.5 + dist(rng));
        uav_id.setLongitude(0.5 + dist(rng));
        uav_id.setAltitude(5);
        item->setData(QVariant::fromValue(uav_id), PositionRole);
    }
}

main.cpp主文件

#include "gcs.h"

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QTimer>

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

    QGuiApplication app(argc, argv);
    GCS gcs;

    QQmlApplicationEngine engine;
    QQmlContext* context = engine.rootContext();
    context->setContextProperty("planner", &gcs);
    const QUrl url(QStringLiteral("qrc:/planner.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    QTimer timer;
    timer.setInterval(1000);
    QObject::connect(&timer, &QTimer::timeout, &gcs, &GCS::triggerPosition);
    timer.start();

    return app.exec();
}

planner.qml规划师.qml

import QtQuick 2.14
import QtQuick.Window 2.14
import QtLocation 5.14
import QtPositioning 5.14

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Plugin {
        id: mapPlugin
        name: "osm"
    }

    Map{
        id: map
        anchors.fill:parent
        plugin: mapPlugin
        center: QtPositioning.coordinate(0.5, 0.5)
        zoomLevel:50

        MapItemView{
            model: planner.uavModel
            delegate: MapCircle{
                id:uavPos
                radius: 2
                color:'black'
                border.width:3
                center: QtPositioning.coordinate(model.position.latitude, model.position.longitude)
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM