Saturday, January 16, 2010

Calling Python from JavaScript in PyQt's QWebkit

QtWebKit makes it very easy to expose methods and properties implemented in Python to JavaScript. Qt will automatically expose Qt-slots and Qt-properties to a JavaScript when a QObject is made available in the frame's JavaScript context.

I think the code speaks for itself
import sys
from PyQt4 import QtCore, QtGui, QtWebKit

"""Html snippet."""
html = """
<html><body>
  <center>
  <script language="JavaScript">
    document.write('<p>Python ' + pyObj.pyVersion + '</p>')
  </script>
  <button onClick="pyObj.showMessage('Hello from WebKit')">Press me</button>
  </center>
</body></html>
"""

class StupidClass(QtCore.QObject):
    """Simple class with one slot and one read-only property."""

    @QtCore.pyqtSlot(str)
    def showMessage(self, msg):
        """Open a message box and display the specified message."""
        QtGui.QMessageBox.information(None, "Info", msg)

    def _pyVersion(self):
        """Return the Python version."""
        return sys.version

    """Python interpreter version property."""
    pyVersion = QtCore.pyqtProperty(str, fget=_pyVersion)

def main():
    app = QtGui.QApplication(sys.argv)

    myObj = StupidClass()

    webView = QtWebKit.QWebView()
    # Make myObj exposed as JavaScript object named 'pyObj'
    webView.page().mainFrame().addToJavaScriptWindowObject("pyObj", myObj)
    webView.setHtml(html)

    window = QtGui.QMainWindow()
    window.setCentralWidget(webView)
    window.show()

    sys.exit(app.exec_())

if __name__ == "__main__":
    main()
Some references:

9 comments:

  1. A minor thing to note is that you should ensure you re-add your object to the window every time the javaScriptWindowObjectCleared() signal is emitted too. There's a C++ example of this on my blog post http://www.kdedevelopers.org/node/4008

    ReplyDelete
  2. Wow! I've been looking for a way to do this for a week straight! This is miles ahead of anything I was able to find for Python-Gobject. And it's from 2010, good lord...

    ReplyDelete
  3. All the day with "Python-Gobject" search too, reading c++ code, and here is! clear and well commented code! Thank you!!!

    ReplyDelete
  4. You're welcome! Glad I can help

    ReplyDelete
  5. Is there anyway to connect with an onItemClick in a loaded .js file? It seems not to work when the code is loaded from a .js on disk.

    ReplyDelete
  6. Sorry, don't know. Haven't been playing anymore with this in years.

    ReplyDelete
  7. This comment has been removed by a blog administrator.

    ReplyDelete
  8. This comment has been removed by a blog administrator.

    ReplyDelete