You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QtLocation添加MapCircle至地图无显示问题求助及代码排查

QtLocation地图添加MapCircle不显示问题

我有一个基于QtQuick Widget的Qt应用,用QtLocation和QtPositioning展示地图。尝试通过C++传入的坐标数组,在组件加载时向地图添加MapCircle,日志显示圆圈已成功添加,但地图上始终看不到。

第一种实现方案(QML直接创建)

QML代码

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtLocation 5.15
import QtPositioning 5.15
import QtQuick.Layouts 1.15

Rectangle {
    id: rec
    function addCircle(latitude, longitude, radius) {
        map.addCircle(latitude, longitude, radius)
    }

    width: 800
    height: 600

    Plugin {
        id: mapPlugin
        name: "osm"
        PluginParameter {
            name: "osm.mapping.custom.host"
            value: "https://tile.openstreetmap.org/"
        }
    }

    Map {
        id: map
        property MapCircle circle
        anchors.fill: parent
        plugin: mapPlugin
        center: QtPositioning.coordinate(70, -175.5)
        zoomLevel: 6

        Component.onCompleted: {
            for (var i = 0; i < myArray.length; i += 2) {
                console.log(QtPositioning.coordinate(myArray[i], myArray[i + 1]));
                var circle = Qt.createQmlObject('import QtPositioning 5.6; import QtLocation 5.6; MapCircle { }', map);
                circle.center = QtPositioning.coordinate(myArray[i], myArray[i + 1]);
                circle.radius = 5000;
                circle.color = 'red';
                circle.z = 1000;
                console.log(circle.center, circle.radius);
                map.addMapItem(circle);
                console.log("Circle added:", circle);
            }
        }
    }
}

C++主文件代码

#include "mainwindow.h"
#include "GSN_model.h"
#include "for_SQLite_db.h"
#include "mapcontroller.h"
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QVariantList>

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    MainWindow w;

    // 创建坐标列表
    QVariantList myArray;
    myArray << 70.3 << -175.4 << 69.3 << -175.4 << 71 << -175.4 ;

    // 向QML上下文注册列表
    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("myArray", myArray);

    const QUrl url(QStringLiteral("qrc:/map.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
        &a, [url](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
        }, Qt::QueuedConnection);
    engine.load(url);

    w.show();
    return a.exec();
}

日志输出

qml: 70° 18' 0.0" N, 175° 24' 0.0" W
qml: 70° 18' 0.0" N, 175° 24' 0.0" W 5000
qml: Circle added: QDeclarativeCircleMapItem(0x243b9fe9c80)
qml: 69° 18' 0.0" N, 175° 24' 0.0" W
qml: 69° 18' 0.0" N, 175° 24' 0.0" W 5000
qml: Circle added: QDeclarativeCircleMapItem(0x243b9fea100)
qml: 71° 0' 0.0" N, 175° 24' 0.0" W
qml: 71° 0' 0.0" N, 175° 24' 0.0" W 5000
qml: Circle added: QDeclarativeCircleMapItem(0x243b9feb000)

第二种实现方案(C++调用QML函数)

main.cpp代码

QQmlApplicationEngine engine;
MapController mapController;

engine.rootContext()->setContextProperty("mapController", &mapController);

const QUrl url(QStringLiteral("qrc:/map.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
    &a, [url, &mapController](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);

        mapController.setRootObject(obj);

        mapController.drawCircle(70.6, -175.6, 10000.0);
        mapController.drawCircle(70.3, -175.4, 5000000);
    }, Qt::QueuedConnection);

engine.load(url);

mapcontroller.h代码

#ifndef MAPCONTROLLER_H
#define MAPCONTROLLER_H

#include <QObject>
#include <QGeoCoordinate>

class MapController : public QObject {
    Q_OBJECT
public:
    explicit MapController(QObject *parent = nullptr);

    Q_INVOKABLE void drawCircle(double latitude, double longitude, double radius);

    void setRootObject(QObject *rootObject);

private:
    QObject *m_rootObject;
};

#endif // MAPCONTROLLER_H

mapcontroller.cpp代码

#include "mapcontroller.h"
#include <QQmlProperty>
#include <QDebug>

MapController::MapController(QObject *parent) : QObject(parent), m_rootObject(nullptr) {}

void MapController::setRootObject(QObject *rootObject) {
    m_rootObject = rootObject;
}

void MapController::drawCircle(double latitude, double longitude, double radius) {
    if (!m_rootObject) {
        qWarning() << "Root object is not set!";
        return;
    }

    QVariant returnedValue;
    QVariant lat = latitude;
    QVariant lon = longitude;
    QVariant rad = radius;

    QMetaObject::invokeMethod(m_rootObject, "addCircle",
                              Q_RETURN_ARG(QVariant, returnedValue),
                              Q_ARG(QVariant, lat),
                              Q_ARG(QVariant, lon),
                              Q_ARG(QVariant, rad));
}

map.qml代码(片段)

...
Item {
    id: circlesLayer
    width: parent.width
    height: parent.height

    function addCircle(latitude, longitude, radius) {
        console.log(QtPositioning.coordinate(latitude, longitude), radius);
        var circle = Qt.createQmlObject('import QtPositioning 5.6; import QtLocation 5.6; MapCircle { }', map);
        circle.center = QtPositioning.coordinate(latitude, longitude);
        circle.radius = radius;
        circle.color = 'red';
        circle.z = 1000;
        console.log(circle.center, circle.radius);

        map.addMapItem(circle);
        console.log("Circle added:", circle);
    }
}

两种方案均显示圆圈已添加,但地图上无法看到。请问问题出在哪里?如何在QtLocation中正确添加显示MapCircle?


解决方案

以下是几个关键问题点及修复方式:

1. 调整MapCircle的半径大小

MapCircle的radius单位是米,你第一个方案中设置的5000(5公里)在缩放级别6的地图上尺寸极小,几乎无法识别。先尝试放大半径,比如设置为50000(50公里),观察是否显示。

2. 改用Component创建MapCircle(更可靠)

使用Qt.createQmlObject动态创建对象可能存在隐式问题,改用预定义Component的方式更稳定:

Map {
    id: map
    ...
    // 预定义圆圈组件
    Component {
        id: circleComponent
        MapCircle {
            color: "#FF0000" // 不透明红色
            border.width: 2
            border.color: "black"
            z: 1000
        }
    }

    Component.onCompleted: {
        for (var i = 0; i < myArray.length; i += 2) {
            var circle = circleComponent.createObject(map);
            circle.center = QtPositioning.coordinate(myArray[i], myArray[i + 1]);
            circle.radius = 50000; // 放大半径测试
            map.addMapItem(circle);
            // 可选:自动定位到圆圈位置
            // map.centerOn(circle.center);
        }
    }
}

3. 确保地图初始化完成后再添加圆圈

Component.onCompleted触发时,地图可能尚未完全加载瓦片或初始化完成,导致地图项无法渲染。可以用Timer延迟添加:

Map {
    id: map
    ...
    Timer {
        interval: 500 // 延迟500毫秒
        running: true
        repeat: false
        onTriggered: {
            // 在这里执行添加圆圈的逻辑
        }
    }
}

4. 统一QML导入版本

你的QML文件导入的是QtLocation 5.15,但创建MapCircle时用的是5.6版本,虽然向下兼容,但保持版本一致可以避免潜在问题:

var circle = Qt.createQmlObject('import QtPositioning 5.15; import QtLocation 5.15; MapCircle { }', map);

5. 验证圆圈可见性样式

为圆圈添加边框、使用不透明颜色,确保不会和地图背景融合:

MapCircle {
    color: "#FF0000"
    border.width: 2
    border.color: "#000000"
    z: 1000
}

内容的提问来源于stack exchange,提问作者Артём Михайлов

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 10:57:02