我正在尝试调用一个 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 .
