在 QML qt 中控制 OSM 映射
Posted
技术标签:
【中文标题】在 QML qt 中控制 OSM 映射【英文标题】:Control OSM map in QML qt 【发布时间】:2021-11-07 01:58:12 【问题描述】:我正在尝试在 Qt 中控制地图,但是我一直遇到以下错误:
QGeoTileRequestManager: Failed to fetch tile (291271,152514,19) 5 times, giving up. Last error message was: 'Permission denied'
我在 C++ 中有解析消息并计算位置的函数:
Map.qml
import QtQuick 2.12
import QtQuick.Window 2.14
import QtQuick.Controls 2.15
import QtLocation 5.6
import QtPositioning 5.6
import QtQuick.Controls.Material 2.12
import QtQuick.Layouts 1.12
import Qt.labs.location 1.0
Page
id: mainWindow
visible: true
function addMarker(latitude, longitude)
var Component = Qt.createComponent("qrc:/Marker.qml")
var item = Component.createObject(window,
coordinate: QtPositioning.coordinate(latitude, longitude)
)
map.addMapItem(item)
Map
id: map
width: mainWindow.width
height: mainWindow.height
plugin: mapPlugin
center: QtPositioning.coordinate(59.91, 10.75)
Component.onCompleted: addMarker(59.91, 10.75)
zoomLevel: 60
Plugin
id: mapPlugin
name: "osm" // "mapboxgl", "esri", ...
// specify plugin parameters if necessary
PluginParameter
name: "osm.mapping.providersrepository.disabled"
value: "true"
PluginParameter
name: "osm.mapping.providersrepository.address"
value: "http://maps-redirect.qt.io/osm/5.6/"
通过Q_PROPERTY设置坐标:
#include <QObject>
class Data : public QObject
Q_OBJECT;
Q_PROPERTY(double gnss_log READ gnss_long WRITE set_gnss_long NOTIFY gnss_long_changed);
Q_PROPERTY(double gnss_lat READ gnss_lat WRITE set_gnss_lat NOTIFY gnss_lat_changed);
public: signals:
void gnss_long_changed();
void gnss_lat_changed();
public slots:
void set_gnss_long(double);
void set_gnss_lat(double);
public:
Data();
double gnss_long();
double gnss_lat();
private:
double m_gnss_long;
double m_gnss_lat;
;
void Data::set_gnss_long(double curr_long)
// Checks whether updated baud rate changed
if (curr_long == m_gnss_long)
return;
m_gnss_long = curr_long;
qDebug() << m_gnss_long;
//Emits signal indicating change
emit gnss_long_changed();
double Data::gnss_long()
return m_gnss_long;
当我运行它时,我得到一个空白屏幕,上面提到了一堆错误。
【问题讨论】:
请提供minimal reproducible example。纬度和经度的值是多少 我添加了一个可重现的例子,坐标在设定的时间间隔内变化 但是到什么值(或它改变的值范围)?您使用的 Qt 版本是什么? Qt 5.15,我需要它们从 -180 到 180。 纬度必须在-90到90之间,经度在-180到180之间,你满足了吗? 【参考方案1】:由于 OP 没有提供 MRE,我的答案只会显示一个演示。逻辑是创建一个暴露位置的QProperty,然后必须做一个绑定:
#include <QGeoCoordinate>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QTimer>
#include <random>
class Data: public QObject
Q_OBJECT
Q_PROPERTY(QGeoCoordinate gnssPosition READ gnssPosition WRITE setGnssPosition NOTIFY gnssPositionChanged)
public:
const QGeoCoordinate &gnssPosition() const
return m_gnssPosition;
void setGnssLatitude(qreal latitude)
QGeoCoordinate coordinate(latitude, m_gnssPosition.longitude());
setGnssPosition(coordinate);
void setGnssLongitude(qreal longitude)
QGeoCoordinate coordinate(m_gnssPosition.latitude(), longitude);
setGnssPosition(coordinate);
void setGnssPosition(const QGeoCoordinate &newGnssPosition)
if (m_gnssPosition == newGnssPosition)
return;
m_gnssPosition = newGnssPosition;
emit gnssPositionChanged();
signals:
void gnssPositionChanged();
private:
QGeoCoordinate m_gnssPosition;
;
int main(int argc, char *argv[])
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
Data data_out;
data_out.setGnssPosition(QGeoCoordinate(59.91273, 10.74609));
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("data_out", &data_out);
const QUrl url(QStringLiteral("qrc:/main.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, &data_out, [&data_out]()
std::random_device rd;
std::mt19937 e2(rd());
std::uniform_real_distribution<> dist(-.05, .05);
QGeoCoordinate coord = data_out.gnssPosition();
coord.setLatitude(coord.latitude() + dist(e2));
coord.setLongitude(coord.longitude() + dist(e2));
data_out.setGnssPosition(coord);
// qDebug() << data_out.gnssPosition();
);
timer.start();
return app.exec();
#include "main.moc"
import QtQuick 2.15
import QtQuick.Window 2.15
import QtLocation 5.15
import QtPositioning 5.15
Window
id: mainWindow
width: 640
height: 480
visible: true
title: qsTr("Hello World")
property Component markerProvider: MapQuickItem
anchorPoint.x: rect.width / 2
anchorPoint.y: rect.height / 2
sourceItem: Rectangle
id: rect
width: 40
height: 40
color: "salmon"
function addMarker(coordinate)
var marker = markerProvider.createObject()
console.log(marker)
marker.coordinate = coordinate
map.addMapItem(marker)
Map
id: map
width: mainWindow.width
height: mainWindow.height
plugin: mapPlugin
center: data_out.gnssPosition
zoomLevel: 12
Plugin
id: mapPlugin
name: "osm" // "mapboxgl", "esri", ...
// specify plugin parameters if necessary
PluginParameter
name: "osm.mapping.providersrepository.disabled"
value: "true"
PluginParameter
name: "osm.mapping.providersrepository.address"
value: "http://maps-redirect.qt.io/osm/5.6/"
Connections
target: data_out
function onGnssPositionChanged()
addMarker(data_out.gnssPosition)
【讨论】:
有没有办法通过来自gnssPositionChanged
的信号而不是定时来触发坐标的变化?
所以如果我要创建一个QObject::connect(&data_out, &Data::gnssPositionChanged, &data_out, [&data_out]()QGeoCoordinate coord = data_out.gnssPosition(); data_out.setGnssPosition(coord); );
并通过设置器在内部设置纬度和经度,那应该可以吗?
我确实了解代码的作用,但我正在尝试找到一种方法将其与我当前的代码合并。我有一个在另一个类中设置经度和纬度的解析器,我已经用data_out.setGnssLongitude(Parser::get_gnss_longitude(data));
和data_out.setGnssLatitude(Parser::get_gnss_latitude(data));
替换了我拥有的函数。这意味着每次更新该位置时都会发出信号gnssPositionChanged
。但是,位置不会随着信号的发射而改变,因此我要征求您对是否需要连接的意见。
让我们continue this discussion in chat。
我明白,但我使用的代码库非常庞大,我根本无法将其最小化。以上是关于在 QML qt 中控制 OSM 映射的主要内容,如果未能解决你的问题,请参考以下文章