TkinterMapView

repository·main·Indexed 20 days ago

https://github.com/tomschimansky/tkintermapview

A Python library providing an interactive, tile-based map widget for Tkinter applications. It supports rendering maps via OpenStreetMap or custom tile servers, setting positions by coordinates or addresses, and adding markers, paths, and polygons. Key features include geocoding utilities, mouse event handling, overlay tile server support, and the ability to use offline tiles via a local database.

Tokens
2.5K
Snippets
8
Records
10
Agent score
23%

What's inside tkintermapview

  1. Overview of TkinterMapView

    main

    TkinterMapView is a tile-based interactive map renderer widget designed for the Python Tkinter library.

    Key features include:

    • Tile Support: Displays OpenStreetMap by default, but allows customization of the primary tile server and supports a second tile server for overlays (e.g., OpenSeaMap).
    • Navigation: Set the widget's focus using geographic coordinates or physical addresses.
    • Annotations: Place markers or draw paths on the map.
    • Integration: Can be embedded into standard Tkinter applications or modern UI libraries like CustomTkinter.
  2. Initialize the TkinterMapView widget

    main

    To use tkintermapview, import tkinter and tkintermapview. The TkinterMapView widget requires a master widget (usually a tkinter.Tk instance) and accepts width, height, and corner_radius as arguments. You can then use standard tkinter geometry managers like .place() to position it.

    import tkinter
    import tkintermapview
    
    # create tkinter window
    root_tk = tkinter.Tk()
    root_tk.geometry("800x600")
    root_tk.title("map_view_example.py")
    
    # create map widget
    map_widget = tkintermapview.TkinterMapView(root_tk, width=800, height=600, corner_radius=0)
    map_widget.place(relx=0.5, rely=0.5, anchor=tkinter.CENTER)
    
    root_tk.mainloop()
  3. Use offline tiles

    main
    To use the map without an internet connection, you can load tiles into a local database. When initializing the TkinterMapView widget, pass the path to your tile database as an argument. You can also provide a max_zoom argument to limit the zoom range to what is available in your database.
  4. Create paths and polygons

    main

    Paths

    Connect multiple positions using set_path(position_list, color, command, name, width, data).

    • position_list: A list of (lat, long) tuples.
    • command: A function called when the path is clicked (receives the path object as an argument).
    • Methods: add_position(pos), remove_position(pos), set_position_list(list), delete().
    • Clear all paths with map_widget.delete_all_path().

    Polygons

    Create shapes using set_polygon(position_list, fill_color, outline_color, border_width, command, name).

    • command: A function called when the polygon is clicked (receives the polygon object as an argument).
    • Methods: add_position(lat, long, index), remove_position(lat, long), delete().
    • Clear all polygons with map_widget.delete_all_polygon().
    # Path example
    path_1 = map_widget.set_path([(52.5, 13.3), (52.6, 13.4)], color="blue")
    path_1.add_position((52.7, 13.5))
    
    # Polygon example
    def on_poly_click(poly):
        print(f"Clicked: {poly.name}")
    
    poly_1 = map_widget.set_polygon([(46.0, 6.0), (46.1, 6.1), (46.2, 6.0)], 
                                    command=on_poly_click, 
                                    name="my_poly")
  5. Set map position by coordinates or address

    main

    You can focus the map on a specific location using decimal coordinates or an address string.

    • Coordinates: Use set_position(lat, long) and set_zoom(level). Zoom levels range from 0 to 19.
    • Address: Use set_address(address_string). This uses the OpenStreetMap Nomatim geocode service.
    • With Marker: Passing marker=True to either method will place a red marker at the location and return a PositionMarker object.
    # By coordinates
    map_widget.set_position(48.860381, 2.338594)  # Paris, France
    map_widget.set_zoom(15)
    
    # By address
    map_widget.set_address("colosseo, rome, italy")
    
    # By address with a returned marker object
    marker_1 = map_widget.set_address("colosseo, rome, italy", marker=True)
    marker_1.set_text("Colosseo in Rome")
  6. Manage PositionMarkers

    main

    Markers can be created without moving the map focus using set_marker(lat, long, text=...).

    Customization Options: set_marker(), set_address(), and set_position() accept: text, font, icon (a PIL.ImageTk.PhotoImage), icon_anchor (e.g., center, n, nw, w, sw, s, ew, e, ne), image (a PhotoImage), image_zoom_visibility (a tuple (min_zoom, max_zoom)), marker_color_circle, marker_color_outside, text_color, and command.

    Marker Methods:

    • set_text(text): Updates the marker label.
    • set_position(lat, long): Moves the marker.
    • change_icon(new_icon): Changes the icon (if an icon was provided at creation).
    • hide_image(bool): Shows or hides the associated image.
    • delete(): Removes the marker.
    • data: An attribute to store arbitrary objects/references.

    Use map_widget.delete_all_marker() to clear all markers.

    # Create a marker
    marker_2 = map_widget.set_marker(52.516268, 13.377695, text="Brandenburger Tor")
    
    # Customize marker
    marker_2.set_text("New Label")
    marker_2.change_icon(my_pil_icon)
    marker_2.hide_image(True)
    
    # Delete marker
    marker_2.delete()
  7. Use utility methods for geocoding

    main

    The library provides several utility functions for converting between coordinates and addresses using the OpenStreetMap provider:

    • convert_coordinates_to_address(lat, long): Returns an address object with attributes like street, housenumber, postal, city, state, country, and latlng.
    • convert_coordinates_to_city(lat, long): Returns the city name as a string.
    • convert_coordinates_to_country(lat, long): Returns the country name as a string.
    • convert_address_to_coordinates(address_string): Returns a (lat, long) tuple or None if not found.
    import tkintermapview
    
    # Get address details
    adr = tkintermapview.convert_coordinates_to_address(51.5122057, -0.0994014)
    print(adr.city, adr.country)
    
    # Get coordinates from address
    coords = tkintermapview.convert_address_to_coordinates("London")
  8. Configure tile servers and overlays

    main

    By default, the widget uses OpenStreetMap. You can change the base map or add an overlay using URLs that include {x}, {y}, and {z} placeholders.

    • Base Map: Use set_tile_server(url, max_zoom=...).
    • Overlay: Use set_overlay_tile_server(url) to add a secondary layer (e.g., railway or sea maps) on top of the base map.

    Example URLs:

    • Google Normal: https://mt0.google.com/vt/lyrs=m&hl=en&x={x}&y={y}&z={z}&s=Ga
    • Google Satellite: https://mt0.google.com/vt/lyrs=s&hl=en&x={x}&y={y}&z={z}&s=Ga
    • Stamen Toner: http://a.tile.stamen.com/toner/{z}/{x}/{y}.png
    # Set Google Satellite as base map
    map_widget.set_tile_server("https://mt0.google.com/vt/lyrs=s&hl=en&x={x}&y={y}&z={z}&s=Ga", max_zoom=22)
    
    # Add a railway overlay
    map_widget.set_overlay_tile_server("http://a.tiles.openrailwaymap.org/standard/{z}/{x}/{y}.png")
  9. Handle mouse events on the map

    main

    You can extend the map's interactivity by adding custom commands to mouse clicks.

    • Right-click menu: Use add_right_click_menu_command(label, command, pass_coords=True). If pass_coords is True, the command function receives the clicked (lat, long) tuple as its argument.
    • Left-click: Use add_left_click_map_command(callback). The callback receives the clicked (lat, long) tuple.
    # Custom right-click menu item
    def add_marker_event(coords):
        map_widget.set_marker(coords[0], coords[1], text="new marker")
    
    map_widget.add_right_click_menu_command(label="Add Marker", 
                                            command=add_marker_event, 
                                            pass_coords=True)
    
    # Custom left-click event
    def left_click_event(coordinates_tuple):
        print("Clicked at:", coordinates_tuple)
    
    map_widget.add_left_click_map_command(left_click_event)