Monday, 18 January 2021

How to add an Ipyleaflet map to a PyQt5 application?

I've created an app using PyQt5 that (amongst others) displays a map.

For the map widget, I've used pyqtlet, but I'm starting to realize that this package is really limited (I want to show different layers, to use a draggable marker, etc.), so I want to transition to ipyleaflet instead.

Except that I cannot get my map to show in the app!

The original code was like so:

import sys
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget, QLabel
from pyqtlet import L, MapWidget


class MapWindow(QWidget):
    def __init__(self, base_coords):
        self.base_coords = base_coords
        # Setting up the widgets and layout
        super().__init__()
        self.layout = QVBoxLayout()
        self.title = QLabel("<b>This is my title</b>")
        self.layout.addWidget(self.title)
        self.mapWidget = MapWidget()
        self.layout.addWidget(self.mapWidget)
        self.setLayout(self.layout)

        # Working with the maps with pyqtlet
        self.map = L.map(self.mapWidget)
        self.map.setView(self.base_coords, zoom=10)
        L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}'
                    ).addTo(self.map)  # ArcGIS_topo layer
        self.marker = L.marker(self.base_coords)
        self.marker.bindPopup('This is my marker')
        self.map.addLayer(self.marker)
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    base_coords = [45.783119, 3.123364]
    widget = MapWindow(base_coords)
    sys.exit(app.exec_())
    

I'm then trying to use this to change to ipyleaflet:

import sys
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget, QLabel
from PyQt5 import QtWebEngineWidgets
from ipyleaflet import Map, Marker, LayersControl, basemaps
from ipywidgets import HTML


class MapWindow(QWidget):
    def __init__(self, base_coords):
        self.base_coords = base_coords
        # Setting up the widgets and layout
        super().__init__()
        self.layout = QVBoxLayout()
        self.title = QLabel("<b>This is my title</b>")
        self.layout.addWidget(self.title)

        # Working with the maps with ipyleaflet
        self.map = Map(center=self.base_coords, basemaps=basemaps.Esri.WorldTopoMap, zoom=10)
        self.layout.addWidget(self.map)

        self.marker = Marker(location=self.base_coords)
        self.marker.popup = HTML(value='This is my marker')
        self.map.add_layer(self.marker)
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    base_coords = [45.783119, 3.123364]
    widget = MapWindow(base_coords)
    sys.exit(app.exec_())

But the addition of the map in the layout doesn't work, I get this error message:

Traceback (most recent call last):
  File "G:\venv\lib\site-packages\IPython\core\interactiveshell.py", line 3418, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-2-bd466e04ab02>", line 1, in <module>
    runfile('G:/Application/short_app - Copie.py', wdir='G:/Application')
  File "C:\Program Files\JetBrains\PyCharm 2020.2.3\plugins\python\helpers\pydev\_pydev_bundle\pydev_umd.py", line 197, in runfile
    pydev_imports.execfile(filename, global_vars, local_vars)  # execute the script
  File "C:\Program Files\JetBrains\PyCharm 2020.2.3\plugins\python\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "G:/Application/short_app - Copie.py", line 29, in <module>
    widget = MapWindow(base_coords)
  File "G:/Application/short_app - Copie.py", line 19, in __init__
    self.layout.addWidget(self.map)
TypeError: addWidget(self, QWidget, stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'Map'

Does anybody know I can add the ipyleaflet map to my application?



from How to add an Ipyleaflet map to a PyQt5 application?

No comments:

Post a Comment