我想用Qt / QML在地图上显示大量的点。这些点在.txt文件中详细说明。
我正在寻找使用的过程但不幸的是,我只通过插件找到一个查询方法来显示来自服务器的地方(osm,google ...)。我不能使用它,这些要点非常具体。
实现此任务的最佳方法是什么?
另外,除了“osm插件”之外,还需要使用“plugin itemsoverlay”来显示特定图层上的这些点吗?
感谢您的帮助。
好的,现在回到代码的战斗中。
这是主要的.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QObject>
#include <QGeoCoordinate>
#include <QDebug>
class NavaidsPoint: public QObject
{
Q_OBJECT
Q_PROPERTY(QGeoCoordinate position READ position WRITE setPosition NOTIFY positionChanged)
public:
NavaidsPoint(QString code, double latitude, double longitude, QString country = "")
{
m_code = code;
m_latitude = latitude;
m_longitude = longitude;
m_country = country;
m_position.setLatitude(latitude);
m_position.setLongitude(longitude);
}
void setPosition(const QGeoCoordinate &c) { //Affectation des nouvelles coordonnées de position
if (m_position == c)
return;
m_position = c;
emit positionChanged(); //Emission du signal de changement de position
}
QGeoCoordinate position() const
{
return m_position; //Lecture des coordonnées de position
}
Q_INVOKABLE QString oaciCode() const {
return m_code;
}
Q_INVOKABLE QString countryCode() const {
return m_country;
}
signals:
void positionChanged();
private:
QGeoCoordinate m_position;
double m_latitude;
double m_longitude;
double m_altitude;
QString m_code;
QString m_country;
};
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
NavaidsPoint oslo("Oslo", 59.9154, 10.7425, "NG");
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("oslo", &oslo);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
#include "main.moc"
和main.qml
import QtQuick 2.6
import QtQuick.Window 2.2
import QtPositioning 5.5
import QtLocation 5.6
Window {
width: 700
height: 500
visible: true
title: qsTr("Test implantation coordonnées")
property variant topLeftEurope: QtPositioning.coordinate(60.5, 0.0)
property variant bottomRightEurope: QtPositioning.coordinate(51.0, 14.0)
property variant viewOfEurope:
QtPositioning.rectangle(topLeftEurope, bottomRightEurope)
Map {
id: mapOfEurope
anchors.centerIn: parent;
anchors.fill: parent
plugin: Plugin {
name: "osm"
}
MapCircle {
center: oslo.position
radius: 5000.0
color: 'green'
border.width: 3
MouseArea {
anchors.fill: parent
onDoubleClicked: {
console.log("Doubleclick on " + oslo.oaciCode())
}
onClicked: {
console.log("Point : " + oslo.oaciCode() + " " + oslo.position + " " + oslo.countryCode())
}
}
}
visibleRegion: viewOfEurope
}
}
奥斯陆这个独特的观点一切正常。现在我需要放置数千点。这种结构不能像那样工作,因为我需要为它们中的每一个实现一个NavaidsPoint,并为它们中的每个实现setContextProperty。同样,在main.QML中,圆圈与对象绑定:
center : oslo.position
此外,我还有oaciCode和countryCode。因此,这部分代码必须是通用的,而不是特定于单个对象。
那么,什么是解决这个问题的最佳方法呢?
我希望能够在这些精确的范围内进入SO范围。
再次感谢您的帮助。
答案 0 :(得分:0)
如果要加载许多元素,一个好的选择是使用MapItemView,这需要一个提供数据的模型,并指出适当的委托。
模型是基于QAbstractListModel
创建的,我们将使用角色将属性公开给QML
,因为它创建的类不一定要从QObject
继承,在这种情况下,它将是以下。
#ifndef NAVAIDSPOINT_H
#define NAVAIDSPOINT_H
#include <QGeoCoordinate>
#include <QString>
class NavaidsPoint
{
public:
NavaidsPoint(QString code, double latitude, double longitude, QString country = ""){
m_code = code;
m_country = country;
m_position.setLatitude(latitude);
m_position.setLongitude(longitude);
m_position.setAltitude(0.0);
}
void setPosition(const QGeoCoordinate &c) { //Affectation des nouvelles coordonnées de position
m_position = c;
}
QGeoCoordinate position() const{
return m_position; //Lecture des coordonnées de position
}
QString oaciCode() const {
return m_code;
}
QString countryCode() const {
return m_country;
}
private:
QGeoCoordinate m_position;
QString m_code;
QString m_country;
};
#endif // NAVAIDSPOINT_H
QAbstractListModel
要求您实施方法rowCount
,data
和roleNames
,同时我已经实现了add方法,您必须通知模型更改,示例如下
#ifndef NAVAIDSMODEL_H
#define NAVAIDSMODEL_H
#include "navaidspoint.h"
#include <QAbstractListModel>
#include <QFile>
#include <QTextStream>
#include <QDebug>
class NavaidsModel : public QAbstractListModel
{
Q_OBJECT
public:
NavaidsModel(QObject *parent = Q_NULLPTR):QAbstractListModel(parent){
}
enum NavaidsRoles {
PositionRole = Qt::UserRole + 1,
OACICodeRole,
CountryCodeRole
};
void readFromCSV(const QString &filename){
QFile file(filename);
if(!file.open(QFile::ReadOnly | QFile::Text))
return;
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
QStringList elements = line.split(",");
if(elements.count()==4){
QString code = elements[0];
double latitude = elements[1].toDouble();
double longitude = elements[2].toDouble();
QString country = elements[3];
NavaidsPoint p(code, latitude, longitude, country);
addNavaidsPoint(p);
}
}
}
void addNavaidsPoint(const NavaidsPoint &point){
beginInsertRows(QModelIndex(), rowCount(), rowCount());
mPoints << point;
endInsertRows();
}
int rowCount(const QModelIndex & parent = QModelIndex()) const{
Q_UNUSED(parent)
return mPoints.count();
}
QVariant data(const QModelIndex & index, int role=Qt::DisplayRole) const {
if (index.row() < 0 || index.row() >= mPoints.count())
return QVariant();
const NavaidsPoint &point = mPoints[index.row()];
if (role == PositionRole)
return QVariant::fromValue(point.position());
else if (role == OACICodeRole)
return point.oaciCode();
else if (role == CountryCodeRole)
return point.countryCode();
return QVariant();
}
protected:
QHash<int, QByteArray> roleNames() const {
QHash<int, QByteArray> roles;
roles[PositionRole] = "position";
roles[OACICodeRole] = "oaci";
roles[CountryCodeRole] = "country";
return roles;
}
private:
QList<NavaidsPoint> mPoints;
};
#endif // NAVAIDSMODEL_H
创建模型后,会添加模型并将其公开给QML:
#include "navaidsmodel.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
NavaidsModel model;
model.readFromCSV("/home/eyllanesc/data.csv"); //from file
model.addNavaidsPoint(NavaidsPoint("Oslo", 59.9154, 10.7425, "NG")); // add new point
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("navaidsModel", &model);
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
最后,MapItemView
与相应的模型和委托一起使用:
import QtQuick 2.6
import QtQuick.Window 2.2
import QtPositioning 5.5
import QtLocation 5.6
Window {
width: 700
height: 500
visible: true
title: qsTr("Test implantation coordonnées")
property variant topLeftEurope: QtPositioning.coordinate(60.5, 0.0)
property variant bottomRightEurope: QtPositioning.coordinate(51.0, 14.0)
property variant viewOfEurope:
QtPositioning.rectangle(topLeftEurope, bottomRightEurope)
Map {
id: mapOfEurope
anchors.centerIn: parent;
anchors.fill: parent
plugin: Plugin {
name: "osm"
}
MapItemView {
model: navaidsModel
delegate: MapCircle{
center: position
radius: 10000
color: 'green'
border.width: 3
MouseArea {
anchors.fill: parent
onDoubleClicked: {
console.log("Doubleclick on " + oaci)
}
onClicked: {
console.log("Point : " + oaci + " " + position + " " + country)
}
}
}
}
visibleRegion: viewOfEurope
}
}
以下link是完整的示例。