Search code examples
pyqt5pyside2qwidgetfolium

Folium map embedded within PyQt displays blank when adding GeoJson to layer


I have PyQt5 app that embeds a folium Map within a QWidget.

Here's a minimal example of the class I wrote :

import folium
import io

from folium.plugins import Draw, MousePosition, HeatMap
from PySide2 import QtWidgets, QtWebEngineWidgets

class FoliumMap(QtWidgets.QWidget):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)
        self.layout = QtWidgets.QVBoxLayout()
        m = folium.Map(
            title='coastlines',
            zoom_start=3)

        data = io.BytesIO()
        m.save(data, close_file=False)
        webView = QtWebEngineWidgets.QWebEngineView()
        webView.setHtml(data.getvalue().decode())
        self.layout.addWidget(webView)
        self.setLayout(self.layout)

If i run my program here's what I have : enter image description here

Now I want to add a GeoJson layer within the __init__ of my class :

folium.GeoJson('data/custom.geo.json', name='coasts').add_to(m)

This results in having a blank Qwidget : enter image description here

If I save the map under html format I am able to see the layer on my web browser: enter image description here

Has anyone an idea on why the layer implementation makes the QWidget blank ? And how to fix this ?


Solution

  • The problem seems to be the following command : webView.setHtml(data.getvalue().decode())

    It is said in the Qt documentation that :

    Content larger than 2 MB cannot be displayed, because setHtml() converts the provided HTML to percent-encoding and places data: in front of it to create the URL that it navigates to. Thereby, the provided code becomes a URL that exceeds the 2 MB limit set by Chromium. If the content is too large, the loadFinished() signal is triggered with success=false.

    My html file weighs 2628 KB > 2MB. So we have to use webView.load() method instead.

    This is the way to go :

    import folium
    import io
    
    from folium.plugins import Draw, MousePosition, HeatMap
    from PySide2 import QtWidgets, QtWebEngineWidgets, QtCore
    
    class FoliumMap(QtWidgets.QWidget):
        def __init__(self, parent=None):
            QtWidgets.QWidget.__init__(self, parent)
            self.layout = QtWidgets.QVBoxLayout()
            m = folium.Map(
                title='coastlines',
                zoom_start=3)
            
            url = "C:/MYPATH/TO/map.html"
            m.save(url)
    
            webView = QtWebEngineWidgets.QWebEngineView()
            html_map = QtCore.QUrl.fromLocalFile(url)
            webView.load(html_map)
    
            self.layout.addWidget(webView)
            self.setLayout(self.layout)