【问题标题】:Adding markers/places to Qt QML Maps?向 Qt QML 地图添加标记/位置?
【发布时间】:2020-07-09 21:24:15
【问题描述】:

美好的一天!我正在设计一个基于 Qt 的 GUI 平台,该平台显示地图并允许用户在地图上添加标记/图钉。 p>

我正在使用以下 QML 在 QtQuickWidget 中渲染地图:

Plugin {
    id: mapPlugin
    name: "osm"
}

我想允许用户使用表单上的按钮在地图上添加交互式图钉。用户可以按住地图上的一个点,这将打开表单,用户可以在其中命名该地点并按OK。

Example of interactive pin

我想要实现的示例: https://webmshare.com/play/5EXV8


  1. 我曾尝试使用 QQmlComponent 和 QQuickView 但我是 不成功 [http://doc.qt.io/qt-5/qtqml-cppintegration-interactqmlfromcpp.html]

  2. 另一种方法是使用 MapItems 在 QML 本身内添加对象,但是 这是非常不直观的。这就是我的 map.qml 的样子: https://gist.github.com/blackvitriol/7941688d6362162888630a28c79f8cd9

项目结构:https://imgur.com/a/P8YAS

谁能告诉我如何让用户在地图上按住左键,然后在该点添加一个标记?

【问题讨论】:

  • 我的意思是创建一个 QML 文件并在同一个文件中添加大量对象(标记)是没有意义的。我尝试将 MapCircle 项目添加到我的 Map.qml 中,但即使这样也不可见。
  • 添加项目结构和map.qml

标签: c++ qt qml qt5


【解决方案1】:

一种可能的解决方案是使用MapItemView 并创建一个存储坐标的模型:

ma​​rkermodel.h

#ifndef MARKERMODEL_H
#define MARKERMODEL_H

#include <QAbstractListModel>
#include <QGeoCoordinate>

class MarkerModel : public QAbstractListModel
{
    Q_OBJECT

public:
    using QAbstractListModel::QAbstractListModel;
    enum MarkerRoles{positionRole = Qt::UserRole + 1};

    Q_INVOKABLE void addMarker(const QGeoCoordinate &coordinate){
        beginInsertRows(QModelIndex(), rowCount(), rowCount());
        m_coordinates.append(coordinate);
        endInsertRows();
    }

    int rowCount(const QModelIndex &parent = QModelIndex()) const override{
        Q_UNUSED(parent)
        return m_coordinates.count();
    }

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override{
        if (index.row() < 0 || index.row() >= m_coordinates.count())
            return QVariant();
        if(role== MarkerModel::positionRole)
            return QVariant::fromValue(m_coordinates[index.row()]);
        return QVariant();
    }

    QHash<int, QByteArray> roleNames() const{
        QHash<int, QByteArray> roles;
        roles[positionRole] = "position";
        return roles;
    }

private:
    QList<QGeoCoordinate> m_coordinates;
};

#endif // MARKERMODEL_H

ma​​in.qml

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

Rectangle {
    width: Screen.width
    height: Screen.height
    visible: true

    Plugin {
        id: mapPlugin
        name: "osm"
    }

    Map {
        id: mapview
        anchors.fill: parent
        plugin: mapPlugin
        center: QtPositioning.coordinate(59.91, 10.75)
        zoomLevel: 14

        MapItemView{
            model: markerModel
            delegate: mapcomponent
        }
    }

    Component {
        id: mapcomponent
        MapQuickItem {
            id: marker
            anchorPoint.x: image.width/4
            anchorPoint.y: image.height
            coordinate: position

            sourceItem: Image {
                id: image
                source: "http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_red.png"
            }
        }
    }

    MouseArea {
        anchors.fill: parent

        onPressAndHold:  {
            var coordinate = mapview.toCoordinate(Qt.point(mouse.x,mouse.y))
            markerModel.addMarker(coordinate)
        }
    }
}

ma​​in.cpp

#include "markermodel.h"

#include <QApplication>
#include <QQuickWidget>
#include <QQmlContext>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QQuickWidget w;
    MarkerModel model;
    w.rootContext()->setContextProperty("markerModel", &model);
    w.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
    w.show();

    return a.exec();
}

完整的例子可以在下面的link找到。

【讨论】:

  • 哇!非常令人印象深刻。这似乎可能是解决方案。我正在使用 QQuickWidget 使用 Qt 设计选项卡,而不是在 main.cpp 中定义。你能告诉我如何设置 w.rootContext()->setContextProperty("markerModel", &model);对于我使用 GUI 设计器实现的 QQuickWidget ?我尝试使用 ui->edge_map->rootContext()->setContextProperty("markerModel", &model); 来引用它但它不起作用。
  • ../mainwindow.cpp:32:32: 错误:无效使用不完整类型'class QQmlContext' ui->edge_map->rootContext()->setContextProperty("markerModel", model); ^
  • 我现在正在处理它,将完成它然后接受答案:)
  • 好的,地图现在有一个空的标记模型覆盖,但我不明白你是如何定义标记(数据类型)的?这是一个非常复杂的答案,感谢您的努力。
  • 这种方法不是很有用,因为标记会被擦除并且不会存储到硬内存中。此外,标记无法通过单击激活。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-22
  • 2017-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-15
  • 2013-04-01
相关资源
最近更新 更多