使用来自 C++ 的信号更新 QML 上的 MapCircle
Update a MapCircle on QML using a signal from C++
我正在尝试从 C++ 中的信号更新 QML 中的 MapCircle,但我一整天都遇到了几个问题。
在我的 class 中,我有一个 Q_PROPERTY
,它是只读的,它保存 QVariantList
中 4 架无人机的 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;
};
然后我将函数定义为:
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");
}
在我的主要功能中,我将 triggerPosition
连接到一个计时器以便定期更新位置
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();
}
然而,当我 运行 我的程序时,有轻微的延迟,我的 mouseArea
变得不可用并且程序崩溃。当我尝试打印经度以查看它是否更新时,初始值多次打印到终端,但随后程序崩溃并且地图上没有 MapCircle
我的 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)
}
}
}
有人可以在这里为我指明正确的方向吗?
如果你要处理来自多个元素的信息,那么最好使用模型(与Repeater一起创建多个元素),因此只需要修改一个项目的角色:
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
#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
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)
}
}
}
}
我正在尝试从 C++ 中的信号更新 QML 中的 MapCircle,但我一整天都遇到了几个问题。
在我的 class 中,我有一个 Q_PROPERTY
,它是只读的,它保存 QVariantList
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;
};
然后我将函数定义为:
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");
}
在我的主要功能中,我将 triggerPosition
连接到一个计时器以便定期更新位置
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();
}
然而,当我 运行 我的程序时,有轻微的延迟,我的 mouseArea
变得不可用并且程序崩溃。当我尝试打印经度以查看它是否更新时,初始值多次打印到终端,但随后程序崩溃并且地图上没有 MapCircle
我的 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)
}
}
}
有人可以在这里为我指明正确的方向吗?
如果你要处理来自多个元素的信息,那么最好使用模型(与Repeater一起创建多个元素),因此只需要修改一个项目的角色:
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
#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
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)
}
}
}
}