Getting Started


Maps are beautiful. They can convey information in a way that words and graphs cannot. As a GIS company, we have many occassions where maps are absolutely critical to show our outputs. Pyqtlet was partly built out of a frustration of having to use Google Earth and KML files for all our mapping needs.


pyqtlet was designed for people familiar with both PyQt5 and Leaflet. It is suggested you go through the respective guides if not already familiar.


pyqtlet does not have any external dependencies apart from PyQt5. So if you already have pyqtlet installed, then you just need to copy the pyqtlet folder into your project folder. You may also install pyqtlet from pip. This will install PyQt5 if it has not been installed already.

pip3 install pyqtlet

Now you’re just an import statement away.

from pyqtlet import L, MapWidget


MapWidget should be used like any other QWidget. The first pyqtlet object to be created needs to be the, along with a reference to the map widget. If you try creating any other pyqtlet object before the map, or the map without the map widget, you will get an error.

# within a QWidget
self.mapWidget = MapWidget() =

Once this has been set up,, and pyqtlet as a whole have methods very similar to leaflet itself. So in case you want to set the view, set a basemap, and add some markers, the code would look something like this…[12.97, 77.59], 10)
self.marker = L.marker([12.934056, 77.610029])
self.marker.bindPopup('Maps are a treasure.')

Similarly, a lot of the other leaflet objects can be found in the L namespace. So polygons, circle markers and feature groups can also be added using code that is essentially identical to its JS counterpart.

Accessing state of the map

Sometimes, it is necessary to access different state attributes of the map. pyqtlet allows this to be done. The variables cannot currently be directly returned by the functions, so a callback approach is followed whenever we need to access state of the map

def setZoomWarning(self, event):
    zoom = event['zoom']
    if zoom < 6:
        self.label.setText('Woah buddy. You\'re flying \
            pretty high. Hope you don\'t have vertigo..')
        self.label.setText('Yup, no worries. A fall from \
            here shoudn\'t hurt... too much.')

def setWarnings(self):

Similarly, we can access different state variables of Leaflet. There is also a custom function called that allows you to get all of the map parameters that leaflet allows you to access. This was written to prevent excessive callback depth in case multiple map state variables are required.


Since a large benefit of having maps is allowing users to draw on them, pyqtlet includes Leaflet.draw by default. Since editting is a fairly core functionality of drawing, and setting it up in leaflet is a little cumbersome, pyqtlet sets it all up in case the user doesn’t want to.

# in __init__ or elsewhere
self.drawControl = L.control.draw()

In order to get what the user has drawn, we will need to access the featureGroup of the draw control. So to print what the user has drawn as a geojson.

self.drawControl.featureGroup.toGeoJSON(lambda x: print(x))

Default initialisation of the draw control creates a L.FeatureGroup and adds it to the map, and sets it as the edit layer for L.Draw, and automatically takes care of adding all the drawn items to it. It also sets the default position as 'topleft', disables drawing of rectangles and circles.

All of these can be overriden. So editting can be disabled by setting the 'edit' key in the options as False. Similarly you can use your own featureGroup as the edittable featureGroup by passing it as a parameter.

Additionally, if you want to handle what gets added to the featureGroup, you can setting handleFeatureGroup as False while initiating the draw control. Then using and L.featureGroup.createAndAddDrawnLayer you can manually handle all the drawn shapes that are added to the map.

Events and Signals

Leaflet and PyQt handle signals and events in different ways. pyqtlet follows the PyQt system of pyqtSignal and pyqtSlot to pass around events. So all the leaflet events have been appropriately mapped to a signal of the same name. x: print(x))

Similarly any other can be accessed as a pyqtSignal. The signals from Leaflet.draw are all prefixed with draw and are camel cased accordingly. So 'draw:created' becomes drawCreated and so on.

Custom JS code

In case there is some JS code that needs to be run, which hasn’t already been implemented in pyqtlet, or is causing some kind of bug, that can also be done. If js objects need to be used, their variable names in the leaflet runtime can be accessed from the .jsName attribute.

If a response is expected from js, then the same callback approach will need to be followed

With all the implemented pyqtlet functionality, runJavaScript and getJsResponse, pretty much all the basic use cases have been covered.

This should be enough to get you started and build all the basic functionality that you might expect and need from a map. Further documentation on the API can be found on the API Documentation page. In case you are interested in the technical details and implementation details, you can refer to the Implementation Details page. For going deeper into the different use cases that pyqtlet allows, refer to the Tutorials page.