【问题标题】:Qt control OSM location from C++Qt 从 C++ 控制 OSM 位置
【发布时间】:2018-06-20 20:04:15
【问题描述】:

在我的 Qt5.9 小部件应用程序项目(Windows)中,我在 ui 中添加了一个 QQuickWidget,并将源文件设置为 QML 文件。

我的目的是在 QQuickWidget 中显示开放的街道地图。通过单击按钮,地图的中心位置应更改为特定的纬度/经度坐标。

地图按预期显示在 QQuickWidget 中,但是,我无法通过单击按钮来更改位置。

我正在使用这个 QML 文件内容来显示地图:

//================================
// map.qml
//================================
import QtQuick 2.0
import QtQuick.Window 2.0
import QtLocation 5.6
import QtPositioning 5.6

Item {
    id: qmlMap

    Plugin {
        id: osmPlugin
        name: "osm"
    }

    Map {
        id: map
        anchors.fill: parent
        plugin: osmPlugin
        center: QtPositioning.coordinate(59.91, 10.75)
        zoomLevel: 10
        objectName: "mainMap"

    MapQuickItem {
      id: marker
      coordinate {latitude: 59.91
                 longitude: 10.75}
      anchorPoint.x: image.width * 0.5
      anchorPoint.y: image.height

      sourceItem: Image {
         id: image
         height: 35
         width: 35
         source: "geotag.png"
      }
            function recenter(lat,lng) {
                  map.clearMapItems();
                  marker.coordinate.latitude = lat;
                  marker.coordinate.longitude = lng;
                  map.addMapItem(marker);
                  map.center.latitude = lat;
                  map.center.longitude = lng;
                  map.update();
            }
    }
    }
}

在应用程序启动时,我可以看到 OSM 以我指定的位置为中心,并且我还可以在正确的位置看到标记。

Loaded map on start up

但是,当我单击按钮从 C++ 调用函数 recenter(lat,lng) 时,似乎什么都没有发生(地图上没有位置变化可见)。

我用于位置更改的 C++ 按钮代码是:

void mapproject::on_btnUpdatePos_clicked()
{
    QQmlEngine engine;
    QQmlComponent component(&engine, "qrc:/map.qml");
    QObject *object = component.create();

    QVariant returnedValue;
    QVariant pos = QVariant(0);

    if(object != NULL){
       QMetaObject::invokeMethod(object, "recenter",
       Q_RETURN_ARG(QVariant, returnedValue),
       Q_ARG(QVariant, pos),
       Q_ARG(QVariant, pos));
    }
}

为什么位置更改不起作用?我的 QML 文件或 C++ 代码中是否有错误?

【问题讨论】:

  • 为什么传递坐标0、0?你试过其他坐标吗?
  • 是的,我也尝试了其他坐标,除了 0, 0。但是我没有看到不同的行为。在按钮功能中创建组件只是为了测试。我的计划是在位置更改生效时将其重新定位到函数之外。
  • main.qml 还是 map.qml? qml 有 2 个名称让我感到困惑
  • 对不起,我把 main.qml 改成了 map.qml
  • 显示它如何将 map.qml 加载到 QQuickWidget

标签: c++ qt qml openstreetmap


【解决方案1】:

假设QQuickWidget是通过Qt Designer添加的,它被称为quickWidget,那么你可以使用ui->quickWidget访问它。

要进行简单搜索,您可以在 MapQuickItem 中设置 objectName:

MapQuickItem {
    id: marker
    objectName: "mapItem"
    coordinate {latitude: 59.91
    [...]

你不应该创建一个新组件,你应该使用QQuickWidget,首先是通过rootObject()方法获取显示QQuickWidget的项目,然后寻找名为mapItem的子项和调用recenterer方法:

void MainWindow::on_btnUpdatePos_clicked()
{
    QQuickItem *item = ui->quickWidget->rootObject();
    QObject *object = item->findChild<QObject*>("mapItem");
    QVariant posx = QVariant(-12.0464);
    QVariant posy = QVariant(-77.0428);

    if(object != NULL){
        QMetaObject::invokeMethod(object, "recenter",
                                  Q_ARG(QVariant, posx),
                                  Q_ARG(QVariant, posy));
    }
}

完整的例子可以在下面的link找到

【讨论】:

  • 非常感谢您发布这个工作示例。我让它在我的项目中工作。
  • @eyllanesc 我正在尝试实现您的代码,但是我一直在QObject *object = item-&gt;findChild&lt;QObject*&gt;("mapItem"); 遇到段错误。我猜它找不到对象什么的,我该怎么办?
猜你喜欢
  • 2021-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多