Добавление / удаление маркеров в quickwidget openstreet map - PullRequest
1 голос
/ 03 июня 2019

Я использую QQuickwidget в моем QT5 gui. Я загрузил на него карту openstreet, добавив соответствующие файлы qml. Добавляя функцию в файл qml, я вызываю ее через файл cpp, используя QMetaObject :: invokeMethod. Эта функция добавляет маркеры в определенных координатах. Это потому, что я хочу контролировать свои маркеры с помощью самого кода C ++.

Моя проблема: я могу успешно загрузить карту и маркеры, но не могу удалить маркеры. Моя цель - показать путь движущегося объекта на карте. Поэтому, используя таймер, я хочу периодически обновлять его позицию. Каждые t_samp секунд я хочу убрать маркер и добавить его куда-нибудь еще.

«элемент», созданный в коде addMarker, добавляется на карту с помощью map.addMapItem (item). При добавлении map.removeMapItem (item) к функции маркер исчезает. Но проблема в том, что я не могу получить доступ к «элементу» вне функции. Поэтому я не могу использовать map.removeMapItem, поскольку не могу ввести маркер. Я также попытался сделать функцию вывода 'item', чтобы затем использовать ее для добавления / удаления маркера. К сожалению, я не знаю тип данных элемента, и поэтому не могу его получить.

mapview.qml:



import QtQuick 2.12
import QtLocation 5.12
import QtPositioning 5.12

Item {

    id: window
    Plugin
    {
        id: mapPlugin
        name:"osm"

    }

    function addMarker(latitude, longitude)
    {
        var component= Qt.createComponent("qrc:///qml/marker.qml")
        var item= component.createObject(window, {coordinate: QtPositioning.coordinate(latitude,longitude)})


        map.addMapItem(item)

    }


    Map
    {
        id: map
        anchors.fill: parent
        plugin: mapPlugin
        center: QtPositioning.coordinate(15.4561,73.8021);
        zoomLevel: 14

    }

}
marker.qml:

import QtQuick 2.12
import QtLocation 5.12
import QtPositioning 5.12

    MapQuickItem
    {
    id: marker
    anchorPoint.x: marker.width / 4
    anchorPoint.y: marker.height

    sourceItem: Image
        {

            id: icon
            source: "qrc:///images/mapmark.png"
            sourceSize.width: 50
            sourceSize.height: 50


        }

    }
mainwindow.cpp: (only relevant snippet)

QObject* target= qobject_cast<QObject*>(ui->quickWidget->rootObject());
    QString functionName= "addMarker";

    QMetaObject::invokeMethod(target,functionName.toUtf8().constData(), Qt::AutoConnection, Q_ARG(QVariant, 15.4561), Q_ARG(QVariant,73.8021));

1 Ответ

0 голосов
/ 03 июня 2019

Вместо экспорта маркера QML в C ++ лучше всего экспортировать QObject из C ++ в QML, и, поскольку вы хотите обрабатывать несколько маркеров, вы должны использовать модель.

Объяснениеподход:

Шаблон MVC - это естественный способ обработки большого количества информации в Qt, и для этого он реализует представления, такие как MapItemView, и модели, которые можно создавать на основе QAbstractXXXModel.Таким образом, только ответственность состоит в том, чтобы специализировать классы для цели, например, реализовать логику простого хранения n элементов и, если есть новый элемент, удалить самый старый.

Почему лучшеэкспортировать QObject в QML? Жизненный цикл объектов в QML обрабатывается QML, поэтому в вашем случае вы можете получить доступ к маркерам в данный момент времени, QML может удалить его, чтобы указатель в C ++ добавлял неЗарезервированная память.Другое преимущество состоит в том, что Q_PROPERTY распознается в QML, а тип данных известен в QML и C ++, в отличие от экспорта объекта QML в C ++, поскольку будут использоваться только свойства QObject или QQuickItem.Также при экспорте с использованием setContextProperty QObject является глобальным.Недостатком является то, что добавляется больше кода.Для получения более подробной информации читайте Взаимодействие с QML из C ++ .

markermodel.h

#ifndef MARKERMODEL_H
#define MARKERMODEL_H

#include <QAbstractListModel>
#include <QGeoCoordinate>

class MarkerModel : public QAbstractListModel
{
    Q_OBJECT
    Q_PROPERTY(QGeoCoordinate current READ current NOTIFY currentChanged)
public:
    enum MarkerRoles{
        PositionRole = Qt::UserRole + 1000,
    };
    explicit MarkerModel(QObject *parent = nullptr);
    void moveMarker(const QGeoCoordinate & coordinate);
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    QHash<int, QByteArray> roleNames() const override;
    int maxMarkers() const;
    void setMaxMarkers(int maxMarkers=0);
    QGeoCoordinate current() const;
signals:
    void currentChanged();
private:
    void insert(int row, const QGeoCoordinate & coordinate);
    void removeLastMarker();
    QList<QGeoCoordinate> m_markers;
    QGeoCoordinate m_current;
    int m_maxMarkers;
};

#endif // MARKERMODEL_H

markermodel.cpp

#include "markermodel.h"

MarkerModel::MarkerModel(QObject *parent)
    : QAbstractListModel(parent),
      m_maxMarkers(0)
{
}

void MarkerModel::moveMarker(const QGeoCoordinate &coordinate)
{
    QGeoCoordinate last = m_current;
    m_current = coordinate;
    Q_EMIT currentChanged();
    if(!last.isValid())
        return;
    if(m_maxMarkers == 0){
        insert(0, last);
        return;
    }
    if(rowCount() >= m_maxMarkers){
        while (rowCount() >= m_maxMarkers)
            removeLastMarker();
        removeLastMarker();
    }
    insert(0, last);
}
int MarkerModel::maxMarkers() const
{
    return m_maxMarkers;
}

void MarkerModel::setMaxMarkers(int maxMarkers)
{
    m_maxMarkers = maxMarkers > 1 ? maxMarkers: 0;
}

QGeoCoordinate MarkerModel::current() const
{
    return m_current;
}

int MarkerModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;
    return m_markers.count();
}

QVariant MarkerModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();
    if(role == PositionRole)
        return QVariant::fromValue(m_markers[index.row()]);
    return QVariant();
}

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

void MarkerModel::insert(int row, const QGeoCoordinate & coordinate)
{
    beginInsertRows(QModelIndex(), row, row);
    m_markers.insert(row, coordinate);
    endInsertRows();
}

void MarkerModel::removeLastMarker()
{
    if(m_markers.isEmpty())
        return;
    beginRemoveRows(QModelIndex(), rowCount()-1, rowCount()-1);
    m_markers.removeLast();
    endRemoveRows();
}

mainwindow.h

// ...
MarkerModel marker_model;
// ...

mainwindow.cpp

// ...
ui->quickWidget->rootContext()->setContextProperty("marker_model", &marker_model);
ui->quickWidget->setSource(QUrl("qrc:/mapview.qml"));
// ...

main.qml

// ...
Map{
    id: map
    anchors.fill: parent
    plugin: mapPlugin
    center: QtPositioning.coordinate(15.4561,73.8021);
    zoomLevel: 14
    Marker{
        coordinate: marker_model.current
    }
    MapItemView{
        model: marker_model
        delegate: Marker{
            coordinate: model.position
        }
    }
}
// ...

Полный пример: здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...