You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt5中使用ipyleaflet替代folium时出现URL构造错误求助

解决PyQt5中嵌入ipyleaflet地图时的URL构造错误

问题背景

  • 大学项目需求:从微控制器获取GPS数据,通过PyQt5的Web组件展示位置
  • 最初使用folium,但移动标记时必须重新渲染地图,操作繁琐
  • 改用ipyleaflet实现标记的动态移动/删除,但ipyleaflet没有folium的_repr_html_()方法直接转换地图为HTML
  • 参考方案生成的HTML在浏览器中可正常运行,但在PyQt5中运行时出现JS错误:
    js: Uncaught TypeError: Failed to construct 'URL': Invalid URL
    

用户代码

主程序代码

import sys
import json
from ipyleaflet import Map, Marker, LayersControl, basemaps
from ui import *
from PyQt5.QtWidgets import QDialog, QApplication

from ipywidgets import HTML, IntSlider
from ipywidgets.embed import embed_minimal_html, embed_data

class MyForm(QDialog):
    def __init__(self):
        super().__init__()
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)

        html_template = """
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>IPyWidget export</title>
        </head>
        <body>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js" integrity="sha256-Ae2Vz/4ePdIu6ZyI/5ZGsYnb+m0JlOmKPjt6XZ9JJkA=" crossorigin="anonymous"></script>
            <script src="https://cdn.jsdelivr.net/npm/@jupyter-widgets/html-manager@^1.0.1/dist/embed-amd.js" crossorigin="anonymous"></script>

            <script type="application/vnd.jupyter.widget-state+json">
              {manager_state}
            </script>
            
            <div id="ipyleaflet-map">
                <script type="application/vnd.jupyter.widget-view+json">
                    {widget_views}
                </script>
            </div>

          </body>
        </html>
        """
    
        self.m = Map(center=(24.179509715480204, 12.66299706912081), zoom=16)
        marker = Marker(location=(24.179509715480204, 12.66299706912081), tooltip="woohhooo")
        self.m.add_layer(marker)
        data = embed_data(views=[self.m])
        manager_state = json.dumps(data['manager_state'])
        widget_views = [json.dumps(data['view_specs'])]
        rendered_template = html_template.format(manager_state=manager_state, widget_views=widget_views)
        self.ui.widget.setHtml(rendered_template)
  
if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MyForm()
    w.show()
    sys.exit(app.exec_())

UI代码

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'untitled.ui'
#
# Created by: PyQt5 UI code generator 5.15.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5 import QtWebEngineWidgets

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(638, 400)
        self.widget = QtWebEngineWidgets.QWebEngineView(Dialog)
        self.widget.setGeometry(QtCore.QRect(9, 9, 621, 390))
        self.widget.setObjectName("widget")

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))

错误原因

使用setHtml()直接加载HTML字符串时,PyQt5的QWebEngineView会将页面视为无基础URL的本地内容,而ipyleaflet嵌入的JS代码在加载依赖资源时,会尝试基于当前页面URL构造新的URL,没有合法基础URL时就会触发"Invalid URL"错误。

解决方案

方法一:保存HTML到本地文件后加载

将生成的HTML内容保存为本地文件,再通过load()方法加载文件的本地URL,为页面提供合法的基础URL:

修改主程序中加载HTML的部分:

import os  # 需要新增导入os模块

# ... 原有代码生成rendered_template ...

# 保存HTML到本地文件
with open("map.html", "w", encoding="utf-8") as f:
    f.write(rendered_template)

# 加载本地文件,使用file://协议
self.ui.widget.load(QtCore.QUrl.fromLocalFile(os.path.abspath("map.html")))

方法二:为setHtml指定基础URL

调用setHtml()时,传入第二个参数指定本地目录作为基础URL,让JS能正确构造资源路径:

修改主程序中加载HTML的部分:

import os  # 需要新增导入os模块

# ... 原有代码生成rendered_template ...

# 指定当前目录为基础URL
base_url = QtCore.QUrl.fromLocalFile(os.path.abspath("./"))
self.ui.widget.setHtml(rendered_template, base_url)

验证

修改后,PyQt5的Web组件即可正常加载ipyleaflet地图,支持标记的动态移动、删除等操作。

内容的提问来源于stack exchange,提问作者Dubaja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 04:15:49