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); } } }
故障原因
- 标记的
MouseArea默认会独占捕获到的鼠标事件,没有开启事件透传,鼠标移出标记范围时,底层地图的MouseArea无法重新获取hover事件控制权,坐标更新逻辑中断。 - 标记的
MouseArea仅实现了onEntered逻辑,缺少鼠标在标记上移动、移出标记时的处理,也没有主动释放事件控制权。 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
相关产品推荐
相关产品推荐

