Search code examples
pythonkivymapview

How can I replace the standard marker with canvas circles on MapView in Kivy?


I want to replace the standard marker of the MapMarkerPopup with a transparent pixel image. Instead I want to draw circles which are shown on the coordinates loaded from a CSV file (in this example just a list). The markers are placed correctly, but circles are not shown.In the code below the transparent image is out commented to avoid error while running the code.

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
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, x, y, **kwargs):
        super(PointCreator, self).__init__(**kwargs)
        # self.source = 'images/transparent_pix.png'
        self.x = x
        self.y = y

        with self.canvas:
            print(f'{self.x} | {self.y}')
            Color(.3, .1, .9, 1)
            Line(circle=(self.x, self.y, 10), width=2)


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"])
            point = PointCreator(lat=lat, lon=lon, x=lat, y=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()

I also tried to load the circles directly inside the add_points() method but with same result. What is wrong in the code?


Solution

  • You can add a rule in your kv for your PointCreator:

    <PointCreator>:
        source: ''
        canvas:
            Color:
                rgba: [.3, .1, .9, 1]
            Line:
                circle: self.x, self.y, 20
    

    And remove the canvas instructions from the actual PointCreator class. I am not confident that the location of the circle is correct.