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

QtLocation QML移出MapQuickItem后MouseArea悬浮坐标停止更新问题

QML地图点位标记悬浮后经纬度显示失效问题

问题现象

  • 基于QtLocation模块开发QML地图应用,通过MapQuickItem添加点位标记
  • 主地图绑定id为mapMouseArea的MouseArea,开启hoverEnabled后,初始状态下鼠标在地图移动可实时读取并显示经纬度,运行正常
  • 点位标记定义在独立的marker.qml文件中,标记自带专属MouseArea:鼠标悬浮在标记上时,可正常将对应位置坐标写入主界面labelLatLon控件
  • 异常表现:鼠标移出标记后,labelLatLon不再随鼠标移动更新坐标,主地图MouseArea不再响应hover悬浮事件,移动鼠标无法刷新经纬度

复现代码

主窗口代码

Rectangle {
    id: mainWindow
    
    visible: true
    
    Plugin {
        id: mapPlugin
        name: "osm"
        PluginParameter {
            name: "osm.mapping.providersrepository.disabled"
            value: "true"
        }
        PluginParameter {
            name: "osm.mapping.providersrepository.address"
            value: "http://maps-redirect.qt.io/osm/5.6/"
        }
    }       
    
    function addMarker(latitude,longitude) {
        
        var Component = Qt.createComponent("qrc:///qml/marker.qml")
        var item = Component.createObject(Item, {
                                              coordinate: QtPositioning.coordinate(latitude, longitude)
                                          })
        map.addMapItem(item);         
    }
            
    function setLatLonBox(coordinate) {    
        labelLatLon.text= "Lat: %1; Lon:%2".arg(coordinate.latitude).arg(coordinate.longitude)  
    }
    
    Map {
        id: map
        
        gesture.enabled: true
        copyrightsVisible : true
        anchors.fill: parent
        plugin: mapPlugin
        center: QtPositioning.coordinate(44.0, 9.3) // La Spezia
        zoomLevel: 10
        Component.onCompleted:addMarker(44.0, 9.3)
        
        
        MouseArea  {
            id: mapMouseArea
            property int pressX : -1
            property int pressY : -1
            property int jitterThreshold : 10
            property int lastX: -1
            property int lastY: -1
            property var coordinate: map.toCoordinate(Qt.point(mouseX, mouseY))
            
            anchors.fill: parent
            acceptedButtons: Qt.LeftButton | Qt.RightButton
            hoverEnabled : true

            ColumnLayout {
                id: layout
                spacing: 5
                z: 5
                                    
                Rectangle {
                    id: latLonArea
                    z: 5
                    width: 320
                    height: 40
                    color: "grey"
                    opacity: 0.7
                    border.color: "black"
                    border.width: 1

                    Label {
                        id: labelLatLon
                        anchors.verticalCenter:  parent.verticalCenter
                        anchors.horizontalCenter:  parent.horizontalCenter
                        font.bold: true
                        color: "black"
                        text: "Lat: %1; Lon:%2".arg(mapMouseArea.coordinate.latitude).arg(mapMouseArea.coordinate.longitude)                            
                    }
                }                    
            }
        }
    }
}

marker.qml代码

MapQuickItem {
    id: marker
    z: 2
    anchorPoint.x: marker.width / 2
    anchorPoint.y: marker.height /2
    
    property int idx
    
    sourceItem: Image{
        id: icon
        source: "../symbols/Red_Cross.png"
        sourceSize.width: 40
        sourceSize.height: 40
        opacity: markerMouseArea.pressed ? 0.6 : 1.0
    }
        
    MouseArea {
        id: markerMouseArea
        property int pressX : -1
        property int pressY : -1
        property int jitterThreshold : 10
        property int lastX: -1
        property int lastY: -1
        anchors.fill: parent
        acceptedButtons: Qt.LeftButton | Qt.RightButton
        hoverEnabled : true
        drag.target: marker
        
        onEntered: {
            var coordinate = map.toCoordinate(Qt.point(mouseX, mouseY));
            setLatLonBox(coordinate);
        }
    }
}

故障原因

  1. 标记的MouseArea默认会独占捕获到的鼠标事件,没有开启事件透传,鼠标移出标记范围时,底层地图的MouseArea无法重新获取hover事件控制权,坐标更新逻辑中断。
  2. 标记的MouseArea仅实现了onEntered逻辑,缺少鼠标在标记上移动、移出标记时的处理,也没有主动释放事件控制权。
  3. addMarker方法创建标记对象时,父对象参数错误传入了全局Item,会导致标记内部访问主界面的map、setLatLonBox等对象时存在作用域异常风险。

修复方案

  • 给标记的MouseArea添加propagateComposedEvents: true属性开启组合事件透传,在每个鼠标事件处理逻辑末尾设置mouse.accepted = false,不独占事件,允许底层地图MouseArea同步接收事件。
  • 补全标记MouseArea的onPositionChanged、onExited事件处理,保证鼠标在标记上移动时坐标正常更新,移出标记时正常交还事件控制权。
  • 修正addMarker方法的对象创建逻辑,将map作为父对象传入,保证作用域访问正常。

修复后marker.qml代码

MapQuickItem {
    id: marker
    z: 2
    anchorPoint.x: marker.width / 2
    anchorPoint.y: marker.height /2
    
    property int idx
    
    sourceItem: Image{
        id: icon
        source: "../symbols/Red_Cross.png"
        sourceSize.width: 40
        sourceSize.height: 40
        opacity: markerMouseArea.pressed ? 0.6 : 1.0
    }
        
    MouseArea {
        id: markerMouseArea
        property int pressX : -1
        property int pressY : -1
        property int jitterThreshold : 10
        property int lastX: -1
        property int lastY: -1
        anchors.fill: parent
        acceptedButtons: Qt.LeftButton | Qt.RightButton
        hoverEnabled : true
        drag.target: marker
        propagateComposedEvents: true

        onEntered: {
            const coordinate = map.toCoordinate(Qt.point(mouseX, mouseY));
            setLatLonBox(coordinate);
            mouse.accepted = false
        }

        onPositionChanged: {
            const coordinate = map.toCoordinate(Qt.point(mouseX, mouseY));
            setLatLonBox(coordinate);
            mouse.accepted = false
        }

        onExited: {
            mouse.accepted = false
        }
    }
}

修复后addMarker方法代码

function addMarker(latitude,longitude) {
    const markerComponent = Qt.createComponent("qrc:///qml/marker.qml")
    const item = markerComponent.createObject(map, {
        coordinate: QtPositioning.coordinate(latitude, longitude)
    })
    map.addMapItem(item);         
}

内容的提问来源于stack exchange,提问作者Gab74

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:27:21