[PyQt] PyQt5 QtWebEngine: can't block python till javascript is finished with a callback function
Daan V.
daanv1987 at gmail.com
Fri May 6 10:28:19 BST 2016
When I call the runJavaScript function of QWebEnginePage with a callback I
can't block the python code on this call. I've tried sleeping, "spinning
the event loop" (Kovid Goyal -
https://riverbankcomputing.com/pipermail/pyqt/2015-January/035324.html) and
a combination of both. The example below shows how the
"call_js_with_callback" keeps waiting.
When this while loop is removed from "call_js_with_callback" the callback
actually happens. This means in an asynchronous environment this would not
be an issue, but when porting a legacy project which was not written with
asynchronous behavior in mind there is no quick way to port. Can anyone
tell me if this is correct or if I've made a mistake and/or there is a
workaround I can use?
Another interesting thing is that a callback method declared as I have it
will crash unless the @pyqtSlot() is changed in an @pyqtSlot(str) (or
something similar I assume). With @pyqtSlot() the callback will retrieve
None as parameter and a silent crash of the application happens. Maybe this
can be added to the
http://pyqt.sourceforge.net/Docs/PyQt5/api/qwebenginepage.html page or an
error message can be returned when the callback fails.
Regards and thanks in advance,
Daan Veltman
from PyQt5.Qt import *
from PyQt5.QtWebEngineWidgets import QWebEnginePage, QWebEngineScript,
QWebEngineView
from time import sleep
class WebPage(QWebEnginePage):
javascript_is_ready = False
@pyqtSlot()
def html_ready(self):
print 'html_ready'
self.html_ready = True
self.call_js_with_callback()
def call_js_with_callback(self):
print 'call_js_with_callback'
self.runJavaScript('js_function("with_callback")', self.callback)
while not self.javascript_is_ready:
print 'processing events'
QApplication.instance().processEvents(QEventLoop.ExcludeUserInputEvents |
QEventLoop.ExcludeSocketNotifiers | QEventLoop.WaitForMoreEvents)
sleep(0.5)
print 'through with sleeping!'
@pyqtSlot(str)
def callback(self, none):
print 'calling back!', none
self.javascript_is_ready = True
app = QApplication([])
page = WebPage()
view = QWebEngineView()
view.setPage(page)
channel = QWebChannel(page)
channel.registerObject('page', page)
page.setWebChannel(channel)
view.setHtml(
'<html>' + '\n'
' <body>' + '\n'
' <script src="
https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>'
+ '\n'
' <script type="text/javascript" src="
https://rawgit.com/qtproject/qtwebchannel/dev/src/webchannel/qwebchannel.js"></script>'
+ '\n'
' <p>Hello world!</p>' + '\n'
' <script type="text/javascript">' + '\n'
' function js_function(text) {' + '\n'
' alert("js_function! " + text);' + '\n'
' }' + '\n'
' </script>' + '\n'
' <script type="text/javascript">' + '\n'
' $(document).ready(function(){' + '\n'
' alert("document ready");' + '\n'
' new QWebChannel(qt.webChannelTransport, function
(channel) {' + '\n'
' page = channel.objects.page;' + '\n'
' page.html_ready();' + '\n'
' });' + '\n'
' });' + '\n'
' </script>' + '\n'
' <p>Done!</p>' + '\n'
' </body>' + '\n'
'</html>')
view.show()
app.exec_()
print 'exit'
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20160506/e4cba032/attachment.html>
More information about the PyQt
mailing list