The Map Widget
Guitares includes an interactive web-based map widget powered by either MapLibre GL
(open-source, recommended) or Mapbox GL (requires an API token).
The map is embedded in the Qt window via a QWebEngineView and communicates with Python
through a bidirectional bridge.
Adding the map widget
Add the map to your YAML config like any other element:
- style: map
id: map
position: {x: 10, y: 180, width: -10, height: -10}
module: map_callbacks
map_style: osm
map_lat: 0.0
map_lon: 0.0
map_zoom: 2
Map element keys
Key |
Type |
Default |
Description |
|---|---|---|---|
id |
str |
Unique ID — required to access the map object later |
|
map_style |
str |
|
Initial basemap style (see basemap styles below) |
map_lat |
float |
|
Initial map center latitude |
map_lon |
float |
|
Initial map center longitude |
map_zoom |
float |
|
Initial zoom level |
map_projection |
str |
|
Map projection: |
Accessing the map object
The map object becomes available after the map has finished loading.
Use the map_ready callback (triggered automatically) to store a reference:
# map_callbacks.py
from app import app
def map_ready(*args):
element = app.gui.window.find_element_by_id("map")
app.map = element.widget
# Set up layers
main = app.map.add_layer("main")
main.add_layer("polygons", type="polygon")
def map_moved(*args):
# Called when the user pans or zooms
pass
Layer system
All map data is organized into a tree of layers. There are two kinds of layer objects:
Container layers — grouping nodes with no visual output, created with
add_layer(id)Data layers — visual layers with a
type, created withadd_layer(id, type="...")
Creating layers
# Container layer
main = app.map.add_layer("main")
# Data layers inside the container
main.add_layer("grid", type="polygon")
main.add_layer("boundaries", type="line")
main.add_layer("stations", type="circle")
Available layer types
Type |
Description |
|---|---|
|
Filled/outlined polygons from a GeoDataFrame |
|
Polygons with click-selection support |
|
Polylines from a GeoDataFrame |
|
Polylines with click-selection support |
|
Point circles from a GeoDataFrame or coordinate lists |
|
Circles with click-selection support |
|
Attribute-colored polygons (colored by a data column) |
|
Heatmap from point data |
|
Interactive drawing layer (polygon, polyline, rectangle) |
|
PNG icon markers at point locations |
|
Raster image overlay (numpy array + extent) |
|
Direct image overlay |
|
Tile-based raster (URL template) |
|
Generic image overlay |
|
Specialized storm track visualization |
Setting layer data
Call set_data() on a data layer to pass it new content.
The input type depends on the layer type:
import geopandas as gpd
# Polygon / line / circle layers: pass a GeoDataFrame
gdf = gpd.read_file("boundaries.geojson")
app.map.layer["main"].layer["boundaries"].set_data(gdf)
# Raster layer: pass a numpy array and extent
app.map.layer["main"].layer["flood_depth"].set_data(
data=depth_array, # 2D numpy array
x0=lon_min, y0=lat_min,
x1=lon_max, y1=lat_max
)
Layer styling
Layer appearance is controlled by attributes set directly on the layer object
before or after set_data():
layer = app.map.layer["main"].layer["polygons"]
layer.fill_color = "blue"
layer.fill_opacity = 0.5
layer.line_color = "black"
layer.line_width = 1.0
Common style attributes:
Attribute |
Description |
|---|---|
|
Fill color (color name, hex string, or |
|
Fill opacity (0.0 – 1.0) |
|
Outline/line color |
|
Line width in pixels |
|
Circle radius in pixels (circle layers) |
|
Color when the mouse hovers over a feature |
|
Color when a feature is selected |
Layer visibility
layer.set_visible(True) # show
layer.set_visible(False) # hide
Draw layer
The draw layer lets users draw features interactively on the map.
The drawn features are stored as a GeoDataFrame accessible via layer.gdf.
draw = app.map.layer["main"].layer["drawing"]
# Start drawing
draw.draw_polygon()
draw.draw_polyline()
draw.draw_rectangle()
# Stop drawing and switch to select mode
draw.stop_drawing()
# Access drawn features
gdf = draw.gdf # GeoDataFrame with all drawn features
Map event callbacks
The map module in your YAML config can define callback functions that are called for map events:
Function name |
When called |
|---|---|
|
Map has loaded and is ready; set up layers here |
|
User panned or zoomed the map |
|
Mouse cursor moved over the map (receives |
Click and selection events are delivered to Python via the layer’s callback attributes:
layer = app.map.layer["main"].layer["polygons"]
layer.callback_click = my_click_callback # called with feature index
Using Mapbox
To use Mapbox GL instead of MapLibre, set map_engine="mapbox" when creating the GUI:
self.gui = GUI(self, config_file="myapp.yml", map_engine="mapbox")
You must also place a file named mapbox_token.txt in the same directory as your
config file, containing your Mapbox public access token on a single line.
Mapbox supports additional basemap styles:
map_style: mapbox://styles/mapbox/streets-v12
map_style: mapbox://styles/mapbox/satellite-v9
map_style: mapbox://styles/mapbox/outdoors-v12
map_style: mapbox://styles/mapbox/light-v11
map_style: mapbox://styles/mapbox/dark-v11