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

Kivy中如何用Canvas绘制的圆形替换MapView的MapMarkerPopup默认标记并解决圆形不显示问题

Kivy中如何用Canvas绘制的圆形替换MapView的MapMarkerPopup默认标记并解决圆形不显示问题

嗨,我来帮你分析下问题所在,以及怎么解决这个圆形不显示的问题:

问题根源

你现在的代码里犯了一个关键错误:把地图的经纬度坐标直接当成了Marker控件内部Canvas的绘制坐标。MapMarkerPopup的lat和lon是用来告诉MapView把这个标记放在地图的哪个地理位置,而Canvas的绘制坐标是相对于Marker控件自身的局部坐标系的,和经纬度完全不是一回事。另外你没给Marker设置合适的尺寸,就算坐标对了,圆也可能出了控件的可视范围。

修复后的代码

我把你的代码做了几处关键修改,现在圆形可以正常显示了:

from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy_garden.mapview import MapMarkerPopup
from kivy.graphics import Color, Line, Ellipse
import pandas as pd

Builder.load_string(
'''
#:import MapView kivy_garden.mapview.MapView
<SimpleRec>
    name: "simple_rec"
    BoxLayout:
        orientation: 'vertical'
        MapView:
            id: smap
            lat: 48
            lon: 7.82
            zoom: 11
        Button:
            text: "Add points"
            on_release: root.add_points()
'''
)

class PointCreator(MapMarkerPopup):
    def __init__(self, **kwargs):
        super(PointCreator, self).__init__(**kwargs)
        # 去掉不需要的x、y参数,用lat和lon控制地图上的位置即可
        # 设置Marker的尺寸,给圆形留出绘制空间
        self.size = (40, 40)
        # 设置锚点为中心,确保圆形和地图坐标对应
        self.anchor = (0.5, 0.5)
        
        with self.canvas:
            Color(.3, .1, .9, 1)
            # 用控件自身的中心坐标绘制圆形,radius设为15(根据size调整)
            # 如果要实心圆用Ellipse,空心圆用Line
            # Line(circle=(self.center_x, self.center_y, 15), width=2)
            Ellipse(pos=(self.center_x -15, self.center_y -15), size=(30,30))

class SimpleRec(Screen):
    def __init__(self, **kwargs):
        super(SimpleRec, self).__init__(**kwargs)

    def add_points(self):
        recordings = pd.DataFrame({
            'lat': [47.9687,47.9999,47.9857,47.9524], 
            'lon': [7.8196,7.8199,7.76850,7.7321]
        })
        print(recordings)
        for index, row in recordings.iterrows():
            lat, lon = float(row["lat"]), float(row["lon"])
            # 只传入lat和lon即可,不需要x、y参数
            point = PointCreator(lat=lat, lon=lon)
            self.ids.smap.add_widget(point)

class MainApp(MDApp):
    def build(self):
        screen_manager = ScreenManager()
        simple_rec = SimpleRec(name='simple_rec')
        screen_manager.add_widget(simple_rec)
        return screen_manager

if __name__ == '__main__':
    MainApp().run()

关键修改点说明

  1. 去掉了多余的x、y参数:MapMarkerPopup的位置完全由lat和lon控制,不需要额外传入x、y,之前的赋值完全是混淆了地理坐标和控件局部坐标。
  2. 设置了Marker的size和anchor:给Marker设置(40,40)的尺寸,确保有足够空间绘制圆形;同时设置anchor=(0.5,0.5)让Marker的中心对准地图上的经纬度点,这样圆形会精准定位在目标坐标上。
  3. 修改了Canvas的绘制坐标:用self.center_x和self.center_y(Marker控件自身的中心)作为圆形的圆心坐标,如果是实心圆用Ellipse,需要调整pos和size确保它以中心为圆心;如果是空心圆用Line(circle=(self.center_x, self.center_y, 15), width=2)即可。

这样修改后,点击"Add points"按钮,你就能在地图上看到紫色的圆形标记了。

备注:内容来源于stack exchange,提问作者jan h

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 13:34:33