我在QT5 gui中使用QQuickwidget。我已经通过相应地添加qml文件在其上加载了一个openstreet地图。 通过在qml文件中添加一个函数,我可以使用QMetaObject :: invokeMethod通过cpp文件对其进行调用。此功能在某些坐标处添加标记。这是因为我想通过c ++代码本身来控制标记。
我的问题:我能够成功加载地图和标记,但是无法删除标记。我的目的是在地图上显示移动物体的路径。因此,我想使用计时器来定期更新其位置。每t_samp秒,我要删除标记并将其添加到其他位置。
使用map.addMapItem(item)将在addMarker代码中创建的“ 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));
答案 0 :(得分:0)
最好将QObject从C ++导出到QML,而不是将QML标记导出到C ++,并且由于要处理多个标记,因此必须使用模型。
方法说明:
MVC模式是Qt处理大量信息的自然方法,为此它实现了诸如MapItemView之类的视图以及可以基于QAbstractXXXModel创建的模型。因此,唯一的责任就是为目标专门化类,例如实现仅保留n个元素的逻辑,如果有新元素,则删除最旧的元素。
为什么将QObject导出到QML更好? QML中的对象生命周期由QML处理,因此在您的情况下,您可以在给定的时间访问标记,QML可以删除标记这样,C ++中的指针将追加非保留的内存。另一个优点是,Q_PROPERTY在QML中可以识别,并且数据类型是QML和C ++已知的,这与将QML对象导出到C ++不同,因为仅会使用QObject或QQuickItem的属性。同样,使用setContextProperty导出时,QObject是全局的。缺点是添加了更多代码。有关更多详细信息,请阅读Interacting with QML from 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
}
}
}
// ...
完整的示例是here