PyQt5中如何让HTML<script>访问QtWebEnginePage.runJavaScript定义的JS变量?
问题原因与解决方案
核心原因
你在构造函数里直接调用page().runJavaScript的时机完全错了——这时候QtWebEngineView的页面还没完成初始化,你定义的mynamespace根本没被注入到SVG加载时的全局上下文里。而且SVG里的<script>是同步执行的,它会在页面加载过程中立刻运行,这时候你提前注入的JS要么还没生效,要么因为页面加载重置了上下文,导致脚本执行时找不到这个命名空间。
具体解决方法
1. 监听页面状态,延迟注入JS
不要在构造函数里急着注入,等页面加载完成后再执行runJavaScript,确保上下文正确:
from PyQt5.QtWebEngineWidgets import QWebEngineView from PyQt5.QtCore import QUrl class MyWebView(QWebEngineView): def __init__(self, parent=None): super().__init__(parent) # 监听页面加载完成信号,触发JS注入 self.loadFinished.connect(self.inject_namespace) # 加载本地SVG文件 self.load(QUrl.fromLocalFile("/your/svg/path/file.svg")) def inject_namespace(self): js_code = """ window.mynamespace = { myfunction: function() { alert('success'); } }; """ self.page().runJavaScript(js_code)
2. 调整SVG脚本的执行时机
如果SVG里的脚本是同步执行的,改成等待DOM完全加载后再调用方法,避免提前执行:
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"> <script type="text/javascript"> // 等DOM加载完成后再调用 window.addEventListener('DOMContentLoaded', function() { mynamespace.myfunction(); }); </script> <!-- 你的SVG图形元素 --> <circle cx="100" cy="100" r="50" fill="red"/> </svg>
3. 用全局脚本注入(最可靠)
直接把mynamespace注册为全局脚本,确保任何页面加载时都会自动注入到主上下文:
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineScript from PyQt5.QtCore import QUrl class MyWebView(QWebEngineView): def __init__(self, parent=None): super().__init__(parent) # 创建全局注入脚本 namespace_script = QWebEngineScript() namespace_script.setSourceCode(""" window.mynamespace = { myfunction: function() { alert('success'); } }; """) namespace_script.setName("MyGlobalNamespace") # 设置在文档创建时注入,确保早于SVG脚本执行 namespace_script.setInjectionPoint(QWebEngineScript.DocumentCreation) namespace_script.setWorldId(QWebEngineScript.MainWorld) namespace_script.setRunsOnSubFrames(False) # 添加到页面脚本集合 self.page().scripts().insert(namespace_script) # 加载SVG self.load(QUrl.fromLocalFile("/your/svg/path/file.svg"))
内容的提问来源于stack exchange,提问作者Silverspur
相关产品推荐
相关产品推荐

