我正在尝试用地图中的折线连接多个GeoCoordinates。坐标存储在模型(QAbstractListModel)类中,在这里我可以在C ++中修改(删除和添加)坐标。
仅显示每个坐标的标记即可正常工作,但是当我将它们与折线连接并从模型中删除一些现有坐标时,折线不会得到更新。
map.qml
import QtQuick 2.0
import QtLocation 5.6
import QtPositioning 5.6
Item {
width: 512
height: 512
visible: true
id: mainWindow
Map { //our map
anchors.fill: parent
id: map
plugin: mapPlugin
zoomLevel: 14
focus: true
Plugin {
id: mapPlugin
name: "osm"
}
MapItemView {
model: markerModel
delegate: mapcomponent
}
MapItemView {
model: markerModel
delegate: MapPolyline {
antialiasing: true
line.color: "darkBlue"
line.width: 3
path: pathRole
}
}
Component {
id: mapcomponent
MapQuickItem{
id: marker
coordinate: positionRole
sourceItem: Image{
id: markerimage
width: 20
height: 30
source: "qrc:/marker.png"
}
anchorPoint.x: markerimage.width / 2
anchorPoint.y: markerimage.height
}
}
MouseArea {
anchors.fill: parent
onClicked: {
var coord = parent.toCoordinate(Qt.point(mouse.x,mouse.y))
markerModel.addMarker(coord)
}
}
}
}
markermodel.h ,用于存储坐标
class MarkerModel : public QAbstractListModel {
Q_OBJECT
public:
using QAbstractListModel::QAbstractListModel;
enum MarkerRoles{positionRole = Qt::UserRole, pathRole};
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();
}
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override {
if(row + count > m_coordinates.count() || row < 0)
return false;
beginRemoveRows(parent, row, row+count-1);
for(int i = 0; i < count; ++i)
m_coordinates.removeAt(row + i);
endRemoveRows();
return true;
}
bool removeRow(int row, const QModelIndex &parent = QModelIndex()) {
return removeRows(row, 1, parent);
}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override {
if (index.row() < 0 || index.row() >= m_coordinates.count())
return QVariant();
if(role == Qt::DisplayRole)
return QVariant::fromValue(index.row());
if(role == MarkerModel::positionRole)
return QVariant::fromValue(m_coordinates[index.row()]);
if(role == MarkerModel::pathRole) {
QVariantList coordlist;
for(auto &geocoord : m_coordinates)
coordlist << QVariant::fromValue(geocoord);
return coordlist;
}
return QVariant();
}
QHash<int, QByteArray> roleNames() const {
QHash<int, QByteArray> roles;
roles[positionRole] = "positionRole";
roles[pathRole] = "pathRole";
return roles;
}
private:
QList<QGeoCoordinate> m_coordinates;
};
显示我的问题的gif:
在删除模型中的行时我错过了什么吗?有没有一种方法可以强制qml使用来自模型的全新数据来渲染折线?
答案 0 :(得分:2)
这里有pathRole
并没有多大意义。对于模型的所有行,此角色均相同。
您显示n MapPolyline
,其中n是坐标数,整个模型只需要一个。
我建议您删除pathRole
,仅在模型中公开path
属性,并在addMarker
和removeRows
中发出其通知信号。
答案 1 :(得分:2)
由于它们表明您的代码存在逻辑错误,因此在我的回答中,我将展示实现,因为@GrecKo已经解释了正确的逻辑:
markermodel.h
#ifndef MARKERMODEL_H
#define MARKERMODEL_H
#include <QAbstractListModel>
#include <QGeoCoordinate>
class MarkerModel : public QAbstractListModel {
Q_OBJECT
Q_PROPERTY(QVariantList path READ path NOTIFY pathChanged)
public:
enum MarkerRoles{positionRole = Qt::UserRole, pathRole};
MarkerModel(QObject *parent=nullptr): QAbstractListModel(parent)
{
connect(this, &QAbstractListModel::rowsInserted, this, &MarkerModel::pathChanged);
connect(this, &QAbstractListModel::rowsRemoved, this, &MarkerModel::pathChanged);
connect(this, &QAbstractListModel::dataChanged, this, &MarkerModel::pathChanged);
connect(this, &QAbstractListModel::modelReset, this, &MarkerModel::pathChanged);
connect(this, &QAbstractListModel::rowsMoved, this, &MarkerModel::pathChanged);
}
Q_INVOKABLE void addMarker(const QGeoCoordinate &coordinate) {
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_coordinates.append(coordinate);
endInsertRows();
}
int rowCount(const QModelIndex &parent = QModelIndex()) const override {
if(parent.isValid()) return 0;
return m_coordinates.count();
}
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override {
if(row + count > m_coordinates.count() || row < 0)
return false;
beginRemoveRows(parent, row, row+count-1);
for(int i = 0; i < count; ++i)
m_coordinates.removeAt(row + i);
endRemoveRows();
return true;
}
bool removeRow(int row, const QModelIndex &parent = QModelIndex()) {
return removeRows(row, 1, parent);
}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override {
if (index.row() < 0 || index.row() >= m_coordinates.count())
return QVariant();
if(role == Qt::DisplayRole)
return QVariant::fromValue(index.row());
else if(role == MarkerModel::positionRole)
return QVariant::fromValue(m_coordinates[index.row()]);
return QVariant();
}
QHash<int, QByteArray> roleNames() const override{
QHash<int, QByteArray> roles;
roles[positionRole] = "positionRole";
return roles;
}
QVariantList path() const{
QVariantList path;
for(const QGeoCoordinate & coord: m_coordinates){
path << QVariant::fromValue(coord);
}
return path;
}
signals:
void pathChanged();
private:
QList<QGeoCoordinate> m_coordinates;
};
#endif // MARKERMODEL_H
*。qml
import QtQuick 2.0
import QtLocation 5.6
import QtPositioning 5.6
Item {
width: 512
height: 512
visible: true
id: mainWindow
Map { //our map
anchors.fill: parent
id: map
plugin: mapPlugin
zoomLevel: 14
focus: true
Plugin {
id: mapPlugin
name: "osm"
}
MapItemView {
model: markerModel
delegate: mapcomponent
}
MapPolyline{
antialiasing: true
line.color: "darkBlue"
line.width: 3
path: markerModel.path
}
Component {
id: mapcomponent
MapQuickItem{
id: marker
coordinate: positionRole
sourceItem: Image{
id: markerimage
width: 20
height: 30
source: "qrc:/marker.png"
}
anchorPoint.x: markerimage.width / 2
anchorPoint.y: markerimage.height
}
}
MouseArea {
anchors.fill: parent
onClicked: {
var coord = parent.toCoordinate(Qt.point(mouse.x,mouse.y))
markerModel.addMarker(coord)
}
}
}
}