带点

时间:2018-04-09 07:18:39

标签: qt qml qt5

我在小部件应用程序中嵌入了一个QML地图。我使用MapQuickItem绘制我在MAP上跟踪的资产的标记。此外,我绘制了前一个跟踪点的历史记录。由于操作员可以添加和删除项目,因此我希望将地图项目和历史记录作为组包含在内,以便我可以轻松删除与资产相关的地图项目。

我是QML的新手,也是JS的新手,所以我通过反复试验来学习。

我想要做的是在折线的每个点上添加一个标记(除了作为实际资产标记的最后一个点)。这些点中的每一个上的标记也是图像(可能是小箭头)。我想根据运动方向旋转此箭头。

所以我有我的Main.qml文件来做地图绘制等。然后我有MapMarker.Qml绘制实际资产的标记。目前图像是硬编码的。然后我有一个AssetTrails.qml文件,目前只是一个Polyline组件。我希望我可以在此路径中添加点标记,因为在删除时删除所有项目都很容易。

有人可能会向我解释如何解决这个问题吗?这可能吗?

我附上我的QML片段以供参考。我意识到这不是很好的代码,但就像我说的那样,我通过反复试验来学习。

Main.qml函数

function addAsset(location, Name)
{
    // Load the map marker.
    var mapmarkercomp = Qt.createComponent("mapmarker.qml");
    assetMarkers.push(mapmarkercomp.createObject(
                          map, {"coordinate": QtPositioning.coordinate(location.latitude,
                                                                       location.longitude)}));

    if (mapLoadErrorHandler(assetMarkers[assetMarkers.length - 1]))
    {
        map.center = QtPositioning.coordinate(location.latitude,
                                              location.longitude);
        map.zoomLevel = 6;
        assetMarkers[assetMarkers.length - 1].name = Name;
        assetMarkers[assetMarkers.length - 1].followMe = true;
        assetMarkers[assetMarkers.length - 1].transparency = 0;
        map.addMapItem(assetMarkers[assetMarkers.length - 1]);
    }
}
function addAssetHistory(assetPath, assetName, Colour)
{
    // Load the polyline asset trail.
    var polylinecomp = Qt.createComponent("mapassettrail.qml");
    assetTrails.push(polylinecomp.createObject(map, {"line.color": Colour}));
    if (mapLoadErrorHandler(assetTrails[assetTrails.length - 1]))
    {
        assetTrails[assetTrails.length - 1].path = assetPath;
        assetTrails[assetTrails.length - 1].objectName = assetName;
        map.addMapItem(assetTrails[assetTrails.length - 1]);
    }
}
function removeAssetHistory(assetName)
{
    // loop through the assetTrails to find object with the correct asset name and then remove it
    var rr;
    for (rr in assetTrails)
    {
        if (assetTrails[rr].objectName === assetName)
        {
            map.removeMapItem(assetTrails[rr]);
            break;
        }
    }
    assetTrails.splice(rr,1);
}
function updateAssetHistory(assetPath, assetName)
{
    // find the relevant asset trail for the assetName
    var rr;
    for (rr in assetTrails)
    {
        if (assetTrails[rr].objectName === assetName)
        {
            assetTrails[rr].path = ( assetPath);
        }
    }
}

MapMarker.qml

import QtQuick 2.5
import QtQuick.Window 2.0
import QtQuick.Controls 1.4
import QtLocation 5.9
import QtPositioning 5.6
import AssetStruct 1.0

MapQuickItem
{
    property int spatialPointHeight: 60
    id: assetMapItem2
    property var name: ""
    property var followMe: false
    property var transparency: 0.5
    anchorPoint.x: assetIcon2.width/2
    anchorPoint.y: assetIcon2.height/2
    visible: true
    sourceItem: Column
    {
        Image
        {
            id: assetIcon2
            sourceSize.width: spatialPointHeight
            sourceSize.height: spatialPointHeight
            width: spatialPointHeight
            height: spatialPointHeight
            // Fade out all icons except for the last one
            opacity: 1 - assetMapItem2.transparency
            source: "qrc:/chopper.png"
            transform: Rotation
            {
                id: assetRotation2
                origin.x: spatialPointHeight/2
                origin.y: spatialPointHeight/2
                angle: 90
            }
        }
        Text
        {
            text: name
            horizontalAlignment: Text.AlignHCenter
            font.bold: true
            width: assetIcon2.width + 10
        }
    }

    Component.onCompleted:
    {
        // map.addMapItem(assetMapItem2);
    }
}

AssetTrail.qml

import QtQuick 2.0
import QtQuick 2.5
import QtQuick.Window 2.0
import QtQuick.Controls 1.4
import QtLocation 5.9
import QtPositioning 5.6
import AssetStruct 1.0

MapPolyline
{
    id: assetPolylineTrail
    line.color: "green"
    line.width: 3
}

所以要解释一下我想做多少一点。见下图。跟踪的资产称为Orion1。它目前的位置是Chopper所在的位置。它的旅行历史轨迹是紫色线。在此行中无法看到之前的报告中此图像中有很多,因此我想添加一个"图像"折线上每个点的点/箭头。如果图像是箭头,我可以使用旋转来指示报告的方向。

Image of Orion being tracked

1 个答案:

答案 0 :(得分:2)

根据我的理解,你有一组积分,其中一些必须是awk -v s1=" " -F"[: ]" 'FNR>1{print $1 s1 $1 OFS $2 OFS $3 OFS $4 s1 "0" s1 $5}' OFS=":" Input_file 的一部分,一部分与MapPolyline一起使用。

可取的是通过模型处理数据,我认为你处理的C ++比MapQuickItem更多,所以它也是一个不错的选择。在这里,我创建了一个项目,用于存储名称,资产坐标和历史坐标列表。继承自QML的模型可以添加元素,此模型由管理QAbstractListModelMapItemView的多个MapPolyline使用。

MapQuickItem

<强>的main.cpp

//assetitem.h

#ifndef ASSETITEM_H
#define ASSETITEM_H

#include <QColor>
#include <QGeoCoordinate>
#include <QString>

class AssetItem{
public:
    QString name() const;
    void setName(const QString &name);

    QGeoCoordinate asset() const;
    void setAsset(const QGeoCoordinate &asset);

    void appendHistory(const QGeoCoordinate &value);
    QList<QGeoCoordinate> getHistory() const;

    QColor getColor() const;
    void setColor(const QColor &color);

private:
    QString mName;
    QGeoCoordinate mAsset;
    QList<QGeoCoordinate> history;
    QColor mColor;
};

#endif // ASSETITEM_H


//assetitem.cpp


#include "assetitem.h"

QString AssetItem::name() const
{
    return mName;
}

void AssetItem::setName(const QString &name)
{
    mName = name;
}

QGeoCoordinate AssetItem::asset() const
{
    return mAsset;
}

void AssetItem::setAsset(const QGeoCoordinate &asset)
{
    if(mAsset.isValid())
        appendHistory(mAsset);
    mAsset = asset;
}

void AssetItem::appendHistory(const QGeoCoordinate &value)
{
    history<< value;
}

QList<QGeoCoordinate> AssetItem::getHistory() const{
    return history;
}

QColor AssetItem::getColor() const
{
    return mColor;
}

void AssetItem::setColor(const QColor &color)
{
    mColor = color;
}

//assetlistmodel.h

#ifndef ASSETLISTMODEL_H
#define ASSETLISTMODEL_H

#include "assetitem.h"

#include <QAbstractListModel>

class AssetListModel : public QAbstractListModel
{
    Q_OBJECT
public:
    using QAbstractListModel::QAbstractListModel;

    enum AirportsRoles{
        NameRole = Qt::UserRole + 1,
        AssetRole,
        HistoryRole,
        ColorRole
    };

    Q_INVOKABLE bool addAsset(QGeoCoordinate coord, const QString & name);
    bool createAsset(QGeoCoordinate coord, const QString & name);

    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;
    bool setData(const QModelIndex &index, const QVariant &value, int role) override;
private:
    QList<AssetItem> mAssets;
};

#endif // ASSETLISTMODEL_H

//assetlistmodel.cpp

#include "assetlistmodel.h"

bool AssetListModel::addAsset(QGeoCoordinate coord, const QString &name)
{
    auto it = std::find_if(mAssets.begin(), mAssets.end(), [&](AssetItem const& obj){
            return obj.name() == name;
} );
    if(it != mAssets.end()){
        //append
        int row = it - mAssets.begin();
        QModelIndex ix = index(row);
        return  setData(ix, QVariant::fromValue(coord), AssetRole);
    }
    else{
        //create
        return createAsset(coord, name);
    }
}

bool AssetListModel::createAsset(QGeoCoordinate coord, const QString &name)
{
    beginInsertRows(QModelIndex(), rowCount(), rowCount());

    AssetItem it;
    it.setName(name);
    it.setAsset(coord);
    it.setColor(QColor(qrand()%255, qrand()%255, qrand()%255));
    mAssets<< it;
    endInsertRows();
    return true;
}


int AssetListModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return mAssets.count();
}

QVariant AssetListModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();
    if(index.row() >= 0 && index.row()<rowCount()){
        const AssetItem &it = mAssets[index.row()];
        if(role==NameRole)
            return it.name();
        else if (role == AssetRole)
            return  QVariant::fromValue(it.asset());
        else if(role == HistoryRole){
            QVariantList history_list;
            QList<QGeoCoordinate> coords = it.getHistory();
            for(const QGeoCoordinate & coord: coords){
                history_list<<QVariant::fromValue(coord);
            }
            return history_list;
        }
        else if(role == ColorRole){
            return it.getColor();
        }
    }
    return QVariant();
}


QHash<int, QByteArray> AssetListModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[NameRole] = "name";
    roles[AssetRole]= "asset";
    roles[HistoryRole] = "history";
    roles[ColorRole] = "color";
    return roles;
}

bool AssetListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (!index.isValid())
        return false;
    if(index.row() >= 0 && index.row()<rowCount()){
        if (role == AssetRole) {
            QGeoCoordinate new_asset(value.value<QGeoCoordinate>());
            mAssets[index.row()].setAsset(new_asset);
            emit dataChanged(index, index, QVector<int>{AssetRole});
            return true;
        }
    }
    return false;
}

<强> main.qml

#include "assetlistmodel.h"

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include<QQmlContext>

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    AssetListModel model;
    QGeoCoordinate coord(41.97732, -87.90801);
     model.addAsset(coord, "testing_name1");
     model.addAsset(coord, "testing_name2");

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("assetmodel", &model);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

<子> 完整的示例可以在以下link中找到。

enter image description here