Silvia González
Silvia González

Reputation: 13

Interactive Map in Kivy

I am trying to put an interactive and editable map using kivy in Python. However, I dont want the typical map that comes using kivy garden and map view, I would like to get a black and White map that when you enter the name of the country on a input box, it gets painted in blue.

The best thing I was able to get is this, which is a black map where with white borders and you can get the name of the country painted in blue when you input it.

import folium
import tkinter as tk
from tkinter import ttk
import webbrowser
import os

class WorldMapApp:
    def __init__(self):
        self.visited_countries = []
        
        # Create window
        self.root = tk.Tk()
        self.root.title("World Travel Map")
        
        # Create GUI elements
        frame = ttk.Frame(self.root, padding="10")
        frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # Country entry
        ttk.Label(frame, text="Enter country name:").grid(row=0, column=0, sticky=tk.W)
        self.country_entry = ttk.Entry(frame, width=30)
        self.country_entry.grid(row=0, column=1, padx=5)
        
        # Add button
        ttk.Button(frame, text="Add Country", command=self.add_country).grid(row=0, column=2, padx=5)
        
        # View map button
        ttk.Button(frame, text="View Map", command=self.show_map).grid(row=0, column=3, padx=5)
        
        # Create initial map
        self.update_map()
    
    def update_map(self):
        # Create map
        m = folium.Map(location=[20, 0], zoom_start=2, tiles='CartoDB dark_matter')
        
        # Add country polygons
        folium.GeoJson(
            'https://raw.githubusercontent.com/python-visualization/folium/master/examples/data/world-countries.json',
            style_function=lambda country: {
                'fillColor': 'blue' if country['properties']['name'] in self.visited_countries else 'black',
                'fillOpacity': 0.7,
                'color': 'white',
                'weight': 1
            }
        ).add_to(m)
        
        # Save map
        self.map_path = 'world_map.html'
        m.save(self.map_path)
    
    def add_country(self):
        country = self.country_entry.get().strip()
        if country:
            self.visited_countries.append(country)
            self.country_entry.delete(0, tk.END)
            self.update_map()
            self.show_map()
    
    def show_map(self):
        webbrowser.open('file://' + os.path.abspath(self.map_path))
    
    def run(self):
        self.root.mainloop()

if __name__ == "__main__":
    app = WorldMapApp()
    app.run()

This is an HTML map that opens in a new window. My question here is: Would be posible to add this kind of map, with smaller dimensions, into a a code that already has some boxes and put in in there?

The code I would like to implement it to is this one.

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.metrics import dp
from kivy.graphics import Color, RoundedRectangle

class Dashboard(BoxLayout):
    pass

class DashboardApp(App):
    def build(self):
        Builder.load_string(KV)
        return Dashboard()

KV = '''
#:import dp kivy.metrics.dp

<Dashboard>:
    orientation: 'vertical'
    padding: dp(10)
    spacing: dp(5)

    ScrollView:
        do_scroll_x: False
        do_scroll_y: True
        bar_width: '10dp'
        bar_color: 0.22, 0.71, 1, 1
        bar_inactive_color: 0.22, 0.71, 1, 0.5
        effect_cls: "ScrollEffect"
        scroll_type: ['content', 'bars']

        BoxLayout:
            orientation: 'vertical'
            size_hint_y: None
            height: dp(700)
            spacing: dp(10)
            padding: dp(15)

            canvas.before:
                Color:
                    rgba: 0.66, 0.85, 0.96, 1
                RoundedRectangle:
                    pos: self.pos
                    size: self.size
                    radius: [dp(15)]

            # First box
            BoxLayout:
                size_hint_y: None
                height: dp(160)
                canvas.before:
                    Color:
                        rgba: 0.22, 0.71, 1, 1
                    RoundedRectangle:
                        pos: self.pos
                        size: self.size
                        radius: [dp(15)]
                    Color:
                        rgba: 1, 1, 1, 1
                    RoundedRectangle:
                        pos: self.pos[0] + dp(2), self.pos[1] + dp(2)
                        size: self.size[0] - dp(4), self.size[1] - dp(4)
                        radius: [dp(13)]

            # Second box
            BoxLayout:
                size_hint_y: None
                height: dp(150)
                canvas.before:
                    Color:
                        rgba: 0.22, 0.71, 1, 1
                    RoundedRectangle:
                        pos: self.pos
                        size: self.size
                        radius: [dp(15)]
                    Color:
                        rgba: 1, 1, 1, 1
                    RoundedRectangle:
                        pos: self.pos[0] + dp(2), self.pos[1] + dp(2)
                        size: self.size[0] - dp(4), self.size[1] - dp(4)
                        radius: [dp(13)]

            # Third box
            BoxLayout:
                size_hint_y: None
                height: dp(180)
                canvas.before:
                    Color:
                        rgba: 0.22, 0.71, 1, 1
                    RoundedRectangle:
                        pos: self.pos
                        size: self.size
                        radius: [dp(15)]
                    Color:
                        rgba: 1, 1, 1, 1
                    RoundedRectangle:
                        pos: self.pos[0] + dp(2), self.pos[1] + dp(2)
                        size: self.size[0] - dp(4), self.size[1] - dp(4)
                        radius: [dp(13)]

            # Fourth box
            BoxLayout:
                size_hint_y: None
                height: dp(150)
                canvas.before:
                    Color:
                        rgba: 0.22, 0.71, 1, 1
                    RoundedRectangle:
                        pos: self.pos
                        size: self.size
                        radius: [dp(15)]
                    Color:
                        rgba: 1, 1, 1, 1
                    RoundedRectangle:
                        pos: self.pos[0] + dp(2), self.pos[1] + dp(2)
                        size: self.size[0] - dp(4), self.size[1] - dp(4)
                        radius: [dp(13)]
'''

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

Thanks in advance for your support and answers,

Silvia

Upvotes: 0

Views: 30

Answers (0)

Related Questions