Skip to main content
 首页 » 编程设计

javascript之PySide、QtWebKit 和 JavaScript 参数类型

2025年05月04日23虾米哥

我正在尝试调用一个 Python 函数,该函数定义为来自在 QWebView 实例中运行的 JavaScript 代码的槽。我已经能够或多或少地设置所有内容,但是在我的一生中无法弄清楚(或找到任何文档)当从内部调用函数时传递给 Python 实现的 Slot 的参数类型带有复杂参数的 JavaScript(例如数组、JSON 对象或 JavaScript 对象,例如 ErrorEvent 对象)。

下面的代码有点复杂但是说明了问题:

import sys 
from PySide.QtGui import QApplication 
from PySide.QtCore import QObject, Slot 
from PySide.QtWebKit import QWebPage, QWebView, QWebElement 
 
 
class JavascriptApi(QObject): 
 
    OBJ_NAME    = 'MyApi' 
    JS_API_INIT = ("window.addEventListener('error', function(e) { " 
                   "    %(objname)s.log_error([e.message, e.filename, e.lineno, e.column]); " 
                   "}, false);" 
                   "window.addEventListener('load', %(objname)s.window_loaded, false);" 
                   "console.log('JavaScript API initialized');") % {"objname": OBJ_NAME} 
 
    def initialize(self, page): 
        f = page.mainFrame() 
        f.addToJavaScriptWindowObject(self.OBJ_NAME, self) 
        f.evaluateJavaScript(self.JS_API_INIT) 
 
    @Slot(list) 
    def log_error(self, error): 
        print error 
        #print "JavaScript Error: %s [%s:%d:%d]" % (message, filename, lineno, column) 
 
    @Slot(QWebElement) 
    def window_loaded(self, window): 
        print "JavaScript window.onload event reported" 
 
 
class InstrumentedWebPage(QWebPage): 
 
    def __init__(self, *args, **kwargs): 
        super(InstrumentedWebPage, self).__init__(*args, **kwargs) 
        self._js_api = JavascriptApi() 
        self.mainFrame().javaScriptWindowObjectCleared.connect(self._init_javascript_api) 
 
    def javaScriptConsoleMessage(self, message, lineNumber, sourceID): 
        print "JavaScript Console Message: %s (%s:%d)" % (message, sourceID, lineNumber) 
 
    def _finished(self, status): 
        print "Finished!" 
        QApplication.instance().quit() 
 
    def _init_javascript_api(self): 
        self._js_api.initialize(self) 
 
 
if __name__ == '__main__': 
    app = QApplication(sys.argv) 
    view = QWebView() 
    view.setPage(InstrumentedWebPage()) 
    view.setHtml('<html><body>This is some HTML' 
                 '<script>foo_bar("syntax error here);</script>' 
                 '</body></html>') 
    view.show() 
    sys.exit(app.exec_()) 

如果你运行它,你会注意到控制台中记录了以下消息:

TypeError: incompatible type of argument(s) in call to log_error(); candidates were 
    log_error(PyObject) (undefined:0) 

那么在 @Slot() 中用于 log_error 的正确类型是什么?顺便说一句,在 window.onerror 和我的 Python 代码之间使用中间 JavaScript 函数的全部原因是出于相同的原因 - window.onerror 使用 ErrorEvent JS 对象调用我的代码,这是我可以捕获的唯一方法它与 @Slot(QWebElement) 一起使用,但后来我不知道如何访问对象属性。

请您参考如下方法:

我也一直在尝试弄清楚如何将复杂类型从 JavaScript 传递到 Python/PySide/QWebView 及其 seems序列化为 JSON是要走的路。

在 JavaScript 方面:

window.addEventListener('error', 
    function(e) {  
        MyApi.log_error(JSON.stringify(e)); // serialize the whole object e 
    },                                      // to JSON (or create a new one if 
    false);                                 // you just need a subset) 

在 Python 方面:

import json 
... 
class JavascriptApi(QObject): 
    @Slot(str) # receive the serialized data as a string 
    def log_error(self, error): 
       data = json.loads(message) # deserialize the JSON on the python side 
                                  # for most complex type, you'll get a dictionary 
                                  # or an array 
       print data 

此方法也可用于相反方向,参见 first link above .