带回调的 runJavaScript 不等待 return
runJavaScript with callback does not wait for return
我刚开始使用 javascript 和 Qt,请多多包涵
我的问题是 runJavaScript
方法。我似乎无法使用延迟的 returned 值获得 运行 的回调函数。例如,以下打印 None
.
js = '''
function returnHello(){
var i = 0;
var wait = setInterval(function() { //arbitrary delay
i++
if(i>2){
return('hello')
}
}, 10);
}
returnHello();
'''
def test(a):
print(a)
mw.reviewer.web.page().runJavaScript(js, test)
我怀疑它与 javascript 运行 的异步方式有关,我尝试使用 javascript 回调方法,但如果 [=28] 有任何延迟=]ing 值,Qt python 回调方法似乎总是接受 undefined
默认 javascript return 值。
我一直在互联网上寻找答案,所以任何帮助都会很棒!
解释:
您似乎不知道异步任务是如何工作的,异步函数没有 return 内部信息,因为在评估分配时,任务尚未执行,也未被阻止直到它被执行。例如,变量"wait"是一个定时器ID,用于取消定时器的执行。因此在这种情况下 runJavaScript 将不起作用。
解决方案:
一种可能的解决方案是使用 Qt WebChannel,基于 我已经实现了以下解决方案:
import os
import sys
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets, QtWebChannel
from jinja2 import Template
class Element(QtCore.QObject):
def __init__(self, name, parent=None):
super(Element, self).__init__(parent)
self._name = name
@property
def name(self):
return self._name
def script(self):
raise NotImplementedError
class TestObject(Element):
def script(self):
_script = r"""
function returnHello(){
var i = 0;
var id_timer = setInterval(function() { //arbitrary delay
i++
if(i>2){
{{name}}.test('hello')
}
}, 10);
}
returnHello();
"""
return Template(_script).render(name=self.name)
@QtCore.pyqtSlot(str)
def test(self, a):
print(a)
class WebEnginePage(QtWebEngineWidgets.QWebEnginePage):
def __init__(self, *args, **kwargs):
super(WebEnginePage, self).__init__(*args, **kwargs)
self.loadFinished.connect(self.onLoadFinished)
self._objects = []
def add_object(self, obj):
self._objects.append(obj)
@QtCore.pyqtSlot(bool)
def onLoadFinished(self, ok):
if ok:
self.load_qwebchannel()
self.load_objects()
def load_qwebchannel(self):
file = QtCore.QFile(":/qtwebchannel/qwebchannel.js")
if file.open(QtCore.QIODevice.ReadOnly):
content = file.readAll()
file.close()
self.runJavaScript(content.data().decode())
if self.webChannel() is None:
channel = QtWebChannel.QWebChannel(self)
self.setWebChannel(channel)
def load_objects(self):
if self.webChannel() is not None:
objects = {obj.name: obj for obj in self._objects}
self.webChannel().registerObjects(objects)
_script = r"""
{% for obj in objects %}
var {{obj}};
{% endfor %}
new QWebChannel(qt.webChannelTransport, function (channel) {
{% for obj in objects %}
{{obj}} = channel.objects.{{obj}};
{% endfor %}
});
"""
self.runJavaScript(Template(_script).render(objects=objects.keys()))
for obj in self._objects:
if isinstance(obj, Element):
self.runJavaScript(obj.script())
class WebPage(QtWebEngineWidgets.QWebEngineView):
def __init__(self, parent=None):
super().__init__(parent)
page = WebEnginePage(self)
self.setPage(page)
test_object = TestObject("test_object", self)
page.add_object(test_object)
self.load(QtCore.QUrl("https://whosebug.com/"))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
web = WebPage()
web.show()
sys.exit(app.exec_())
我刚开始使用 javascript 和 Qt,请多多包涵
我的问题是 runJavaScript
方法。我似乎无法使用延迟的 returned 值获得 运行 的回调函数。例如,以下打印 None
.
js = '''
function returnHello(){
var i = 0;
var wait = setInterval(function() { //arbitrary delay
i++
if(i>2){
return('hello')
}
}, 10);
}
returnHello();
'''
def test(a):
print(a)
mw.reviewer.web.page().runJavaScript(js, test)
我怀疑它与 javascript 运行 的异步方式有关,我尝试使用 javascript 回调方法,但如果 [=28] 有任何延迟=]ing 值,Qt python 回调方法似乎总是接受 undefined
默认 javascript return 值。
我一直在互联网上寻找答案,所以任何帮助都会很棒!
解释:
您似乎不知道异步任务是如何工作的,异步函数没有 return 内部信息,因为在评估分配时,任务尚未执行,也未被阻止直到它被执行。例如,变量"wait"是一个定时器ID,用于取消定时器的执行。因此在这种情况下 runJavaScript 将不起作用。
解决方案:
一种可能的解决方案是使用 Qt WebChannel,基于
import os
import sys
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets, QtWebChannel
from jinja2 import Template
class Element(QtCore.QObject):
def __init__(self, name, parent=None):
super(Element, self).__init__(parent)
self._name = name
@property
def name(self):
return self._name
def script(self):
raise NotImplementedError
class TestObject(Element):
def script(self):
_script = r"""
function returnHello(){
var i = 0;
var id_timer = setInterval(function() { //arbitrary delay
i++
if(i>2){
{{name}}.test('hello')
}
}, 10);
}
returnHello();
"""
return Template(_script).render(name=self.name)
@QtCore.pyqtSlot(str)
def test(self, a):
print(a)
class WebEnginePage(QtWebEngineWidgets.QWebEnginePage):
def __init__(self, *args, **kwargs):
super(WebEnginePage, self).__init__(*args, **kwargs)
self.loadFinished.connect(self.onLoadFinished)
self._objects = []
def add_object(self, obj):
self._objects.append(obj)
@QtCore.pyqtSlot(bool)
def onLoadFinished(self, ok):
if ok:
self.load_qwebchannel()
self.load_objects()
def load_qwebchannel(self):
file = QtCore.QFile(":/qtwebchannel/qwebchannel.js")
if file.open(QtCore.QIODevice.ReadOnly):
content = file.readAll()
file.close()
self.runJavaScript(content.data().decode())
if self.webChannel() is None:
channel = QtWebChannel.QWebChannel(self)
self.setWebChannel(channel)
def load_objects(self):
if self.webChannel() is not None:
objects = {obj.name: obj for obj in self._objects}
self.webChannel().registerObjects(objects)
_script = r"""
{% for obj in objects %}
var {{obj}};
{% endfor %}
new QWebChannel(qt.webChannelTransport, function (channel) {
{% for obj in objects %}
{{obj}} = channel.objects.{{obj}};
{% endfor %}
});
"""
self.runJavaScript(Template(_script).render(objects=objects.keys()))
for obj in self._objects:
if isinstance(obj, Element):
self.runJavaScript(obj.script())
class WebPage(QtWebEngineWidgets.QWebEngineView):
def __init__(self, parent=None):
super().__init__(parent)
page = WebEnginePage(self)
self.setPage(page)
test_object = TestObject("test_object", self)
page.add_object(test_object)
self.load(QtCore.QUrl("https://whosebug.com/"))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
web = WebPage()
web.show()
sys.exit(app.exec_())