向 QML 地图添加新地点不起作用
Adding new places to the QML map is not working
我目前正在创建一个可以在地图上标记地点的程序。
map.qml:
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtLocation 5.6
import QtPositioning 5.6
Rectangle {
ListModel {
id: locationModel
}
Plugin {
id: mapPlugin
name: "esri"
}
Map {
id: place
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(51.5, 0.1)
zoomLevel: 7
MapItemView
{
model: locationModel
delegate: mapcomponent
}
}
Component {
id: mapcomponent
MapQuickItem {
id: marker
anchorPoint.x: image.width/2
anchorPoint.y: image.height/2
coordinate: QtPositioning.coordinate(lat, lon)
sourceItem: Image {
id: image
width: 100
height: 50
source: "qrc:/rec/marker.png"
}
}
}
function addPlace(lat: double, lon: double){
locationModel.append({"lat": lat, "lon": lon})
console.log("Done")
}
}
mainwindow.cpp:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->quickWidget->setSource(QUrl("qrc:/rec/map.qml"));
QQmlComponent component(ui->quickWidget->engine(), ui->quickWidget->source());
object = component.create();
}
/*Some not interesting code.*/
void MainWindow::on_pushButton_4_clicked()
{
double lat = 50.00;
double lon = 20.00;
QMetaObject::invokeMethod(object, "addDevice",
Q_ARG(double, lat),
Q_ARG(double, lon));
}
object
在 mainwindow.h 中定义如下:QObject *object;
。
单击某个按钮时,从 C++ 文件调用 add place
函数。不幸的是,由于某种原因,此功能无法正常工作。调用后,控制台中会出现“完成”消息,地图上要标记的点的位置将添加到 ListModel 中。不幸的是,标记没有出现在地图上。我究竟做错了什么?如有任何建议,我将不胜感激。
问题是您正在使用新地图创建新组件,并将标记添加到新的不可见地图。
与其将 QML 对象暴露给 C++,不如做相反的事情:
#ifndef PLACEHELPER_H
#define PLACEHELPER_H
#include <QObject>
class PlaceHelper : public QObject
{
Q_OBJECT
public:
explicit PlaceHelper(QObject *parent = nullptr);
void addPlace(double latitude, double longitude);
Q_SIGNALS:
void add(double latitude, double longitude);
};
#endif // PLACEHELPER_H
#include "placehelper.h"
PlaceHelper::PlaceHelper(QObject *parent) : QObject(parent)
{
}
void PlaceHelper::addPlace(double latitude, double longitude)
{
Q_EMIT add(latitude, longitude);
}
*.h
// ..
private:
Ui::MainWindow *ui;
PlaceHelper placeHelper;
};
*.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QQmlContext>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->quickWidget->rootContext()->setContextProperty("placeHelper", &placeHelper);
ui->quickWidget->setSource(QUrl("qrc:/rec/map.qml"));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_4_clicked()
{
double lat = 50.00;
double lon = 0.10;
placeHelper.addPlace(lat, lon);
}
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtLocation 5.6
import QtPositioning 5.6
Rectangle {
ListModel {
id: locationModel
}
Plugin {
id: mapPlugin
name: "esri"
}
Map {
id: place
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(51.5, 0.1)
zoomLevel: 7
MapItemView
{
model: locationModel
delegate: mapcomponent
}
}
Component {
id: mapcomponent
MapQuickItem {
id: marker
anchorPoint.x: image.width/2
anchorPoint.y: image.height/2
coordinate: QtPositioning.coordinate(lat, lon)
sourceItem: Image {
id: image
width: 100
height: 50
source: "qrc:/rec/marker.png"
}
}
}
Connections{
target: placeHelper
function onAdd(latitude, longitude){
locationModel.append({"lat": latitude, "lon": longitude})
}
}
}
另一种解决方案是用C++实现模型并导出到QML:
#ifndef PLACEMODEL_H
#define PLACEMODEL_H
#include <QStandardItemModel>
class PlaceModel: public QStandardItemModel
{
Q_OBJECT
public:
enum PlaceRoles {
LatitudeRole = Qt::UserRole + 1,
LongitudeRole
};
PlaceModel(QObject *parent=nullptr);
Q_INVOKABLE void addPlace(double longitude, double latitude);
};
#endif // PLACEMODEL_H
#include "placemodel.h"
PlaceModel::PlaceModel(QObject *parent):
QStandardItemModel(parent)
{
setItemRoleNames({{LatitudeRole, "lat"},
{LongitudeRole, "lon"}});
}
void PlaceModel::addPlace(double latitude, double longitude)
{
QStandardItem *item = new QStandardItem;
item->setData(latitude, LatitudeRole);
item->setData(longitude, LongitudeRole);
appendRow(item);
}
*.h
private:
Ui::MainWindow *ui;
PlaceModel placeModel;
*.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QQmlContext>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->quickWidget->rootContext()->setContextProperty("placeModel", &placeModel);
ui->quickWidget->setSource(QUrl("qrc:/rec/map.qml"));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_4_clicked()
{
double lat = 50.00;
double lon = 0.10;
placeModel.addPlace(lat, lon);
}
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtLocation 5.6
import QtPositioning 5.6
Rectangle {
Plugin {
id: mapPlugin
name: "esri"
}
Map {
id: place
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(51.5, 0.1)
zoomLevel: 7
MapItemView
{
id: mapView
model: placeModel
delegate: mapcomponent
}
}
Component {
id: mapcomponent
MapQuickItem {
id: marker
anchorPoint.x: image.width/2
anchorPoint.y: image.height/2
coordinate: QtPositioning.coordinate(lat, lon)
sourceItem: Image {
id: image
width: 100
height: 50
source: "qrc:/rec/marker.png"
}
}
}
}
我目前正在创建一个可以在地图上标记地点的程序。
map.qml:
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtLocation 5.6
import QtPositioning 5.6
Rectangle {
ListModel {
id: locationModel
}
Plugin {
id: mapPlugin
name: "esri"
}
Map {
id: place
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(51.5, 0.1)
zoomLevel: 7
MapItemView
{
model: locationModel
delegate: mapcomponent
}
}
Component {
id: mapcomponent
MapQuickItem {
id: marker
anchorPoint.x: image.width/2
anchorPoint.y: image.height/2
coordinate: QtPositioning.coordinate(lat, lon)
sourceItem: Image {
id: image
width: 100
height: 50
source: "qrc:/rec/marker.png"
}
}
}
function addPlace(lat: double, lon: double){
locationModel.append({"lat": lat, "lon": lon})
console.log("Done")
}
}
mainwindow.cpp:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->quickWidget->setSource(QUrl("qrc:/rec/map.qml"));
QQmlComponent component(ui->quickWidget->engine(), ui->quickWidget->source());
object = component.create();
}
/*Some not interesting code.*/
void MainWindow::on_pushButton_4_clicked()
{
double lat = 50.00;
double lon = 20.00;
QMetaObject::invokeMethod(object, "addDevice",
Q_ARG(double, lat),
Q_ARG(double, lon));
}
object
在 mainwindow.h 中定义如下:QObject *object;
。
单击某个按钮时,从 C++ 文件调用 add place
函数。不幸的是,由于某种原因,此功能无法正常工作。调用后,控制台中会出现“完成”消息,地图上要标记的点的位置将添加到 ListModel 中。不幸的是,标记没有出现在地图上。我究竟做错了什么?如有任何建议,我将不胜感激。
问题是您正在使用新地图创建新组件,并将标记添加到新的不可见地图。
与其将 QML 对象暴露给 C++,不如做相反的事情:
#ifndef PLACEHELPER_H
#define PLACEHELPER_H
#include <QObject>
class PlaceHelper : public QObject
{
Q_OBJECT
public:
explicit PlaceHelper(QObject *parent = nullptr);
void addPlace(double latitude, double longitude);
Q_SIGNALS:
void add(double latitude, double longitude);
};
#endif // PLACEHELPER_H
#include "placehelper.h"
PlaceHelper::PlaceHelper(QObject *parent) : QObject(parent)
{
}
void PlaceHelper::addPlace(double latitude, double longitude)
{
Q_EMIT add(latitude, longitude);
}
*.h
// ..
private:
Ui::MainWindow *ui;
PlaceHelper placeHelper;
};
*.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QQmlContext>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->quickWidget->rootContext()->setContextProperty("placeHelper", &placeHelper);
ui->quickWidget->setSource(QUrl("qrc:/rec/map.qml"));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_4_clicked()
{
double lat = 50.00;
double lon = 0.10;
placeHelper.addPlace(lat, lon);
}
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtLocation 5.6
import QtPositioning 5.6
Rectangle {
ListModel {
id: locationModel
}
Plugin {
id: mapPlugin
name: "esri"
}
Map {
id: place
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(51.5, 0.1)
zoomLevel: 7
MapItemView
{
model: locationModel
delegate: mapcomponent
}
}
Component {
id: mapcomponent
MapQuickItem {
id: marker
anchorPoint.x: image.width/2
anchorPoint.y: image.height/2
coordinate: QtPositioning.coordinate(lat, lon)
sourceItem: Image {
id: image
width: 100
height: 50
source: "qrc:/rec/marker.png"
}
}
}
Connections{
target: placeHelper
function onAdd(latitude, longitude){
locationModel.append({"lat": latitude, "lon": longitude})
}
}
}
另一种解决方案是用C++实现模型并导出到QML:
#ifndef PLACEMODEL_H
#define PLACEMODEL_H
#include <QStandardItemModel>
class PlaceModel: public QStandardItemModel
{
Q_OBJECT
public:
enum PlaceRoles {
LatitudeRole = Qt::UserRole + 1,
LongitudeRole
};
PlaceModel(QObject *parent=nullptr);
Q_INVOKABLE void addPlace(double longitude, double latitude);
};
#endif // PLACEMODEL_H
#include "placemodel.h"
PlaceModel::PlaceModel(QObject *parent):
QStandardItemModel(parent)
{
setItemRoleNames({{LatitudeRole, "lat"},
{LongitudeRole, "lon"}});
}
void PlaceModel::addPlace(double latitude, double longitude)
{
QStandardItem *item = new QStandardItem;
item->setData(latitude, LatitudeRole);
item->setData(longitude, LongitudeRole);
appendRow(item);
}
*.h
private:
Ui::MainWindow *ui;
PlaceModel placeModel;
*.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QQmlContext>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->quickWidget->rootContext()->setContextProperty("placeModel", &placeModel);
ui->quickWidget->setSource(QUrl("qrc:/rec/map.qml"));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_4_clicked()
{
double lat = 50.00;
double lon = 0.10;
placeModel.addPlace(lat, lon);
}
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtLocation 5.6
import QtPositioning 5.6
Rectangle {
Plugin {
id: mapPlugin
name: "esri"
}
Map {
id: place
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(51.5, 0.1)
zoomLevel: 7
MapItemView
{
id: mapView
model: placeModel
delegate: mapcomponent
}
}
Component {
id: mapcomponent
MapQuickItem {
id: marker
anchorPoint.x: image.width/2
anchorPoint.y: image.height/2
coordinate: QtPositioning.coordinate(lat, lon)
sourceItem: Image {
id: image
width: 100
height: 50
source: "qrc:/rec/marker.png"
}
}
}
}