Web Content with QWebEngine
The QtWebEngine module embeds the Chromium browser engine in the Qt app: the QWebEngineView is the widget that renders the web content (the load the url, the setHtml the inline), and the QWebEnginePage is the page (the runJavaScript the JS bridge, the profile the storage). The value is the hybrid: the app's native widgets around the web content (the toolbar, the sidebar, the status bar are the Qt's, the content is the web's), and the JS bridge (the runJavaScript the Python-to-JS, the QWebChannel the two-way). This chapter covers the QWebEngineView (the load, the setHtml, the titleChanged), the QWebEnginePage (the runJavaScript the bridge, the profile the storage), and the QWebChannel (the two-way Python-JS, the qwebchannel.js).
The QWebEngineView: The Web Content
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication, QMainWindow
import sys
app = QApplication(sys.argv)
# the VIEW: the QWebEngineView (the the web content widget)
view = QWebEngineView()
window = QMainWindow()
window.setCentralWidget(view)
window.resize(800, 600)
# the LOAD: the url (the the network's, the the http)
view.load(QUrl("https://example.com"))
# the the setHtml: the inline (the the html string, the
# the the base url for the relative)
# view.setHtml("<h1>the inline</h1>")
# the SIGNALS: the the page's (the the load's)
def on_title_changed(title):
window.setWindowTitle(title) # the the native window
# title is the the web page's (the the hybrid: the
# the web content drives the the native frame)
view.titleChanged.connect(on_title_changed)
def on_load_finished(ok):
print("the loaded:", ok)
view.loadFinished.connect(on_load_finished)
# the the navigation: the the back / the forward (the the
# the page's the history, the the native button's)
# view.back(), view.forward(), view.reload()
window.show()
sys.exit(app.exec_())
The QWebEngineView is the web content widget: the load(QUrl) (the network's url, the async, the loadFinished signal the completion), the setHtml (the inline html, the base url for the relative), and the signals (the titleChanged the page's title, the loadFinished the load's). The hybrid is the point: the QWebEngineView is the QWidget (the central widget, the child, the layout's), and the native frame (the QMainWindow, the toolbar, the status bar) is the Qt's - the web content drives the native (the titleChanged to the setWindowTitle), and the navigation (the back, the forward, the reload) is the native button's. The QWebEngineView is the Chromium engine in the Qt widget, and the web content is the widget's content - the hybrid the app's native chrome around the web's content, and the titleChanged the bridge from the web to the native.
The QWebEnginePage: The JS Bridge
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage
from PyQt5.QtCore import QUrl, pyqtSlot
from PyQt5.QtWidgets import QApplication
import sys
app = QApplication(sys.argv)
# the PAGE: the QWebEnginePage (the the page's the logic)
page = QWebEnginePage()
view = QWebEngineView()
view.setPage(page) # the the view's page (the the custom)
# the runJavaScript: the PYTHON -> the JS (the the eval,
# the the callback is the the result)
def on_js_result(result):
print("the js returned:", result)
page.runJavaScript("document.title", on_js_result)
# the the JS's the result is the the callback (the the
# the async, the the event loop's)
# the the JS -> the PYTHON: the the QWebChannel (the the
# the next section) - the the two-way, the the object's
# the the slot's the the JS's the the call
# the the profile: the the storage (the the cookies, the
# the localStorage, the the cache) - the the QWebEngine
# Profile (the the per-app, the the persistent)
# the the profile's the the storage is the the app's
# (the the QWebEngineProfile the the default, the the
# the persistent storage the the app's)
The QWebEnginePage is the page's logic: the runJavaScript (the Python-to-JS - the eval of the JS string, the callback the result, the async the event loop's), the setPage (the view's custom page), and the profile (the storage - the cookies, the localStorage, the cache, the QWebEngineProfile the per-app). The runJavaScript is the one-way bridge: the Python calls the JS (the document.title the example), and the callback is the result (the async, the event loop dispatches it). The two-way is the QWebChannel (the next section): the Python object's slots are the JS's callable, and the JS's calls reach the Python (the qwebchannel.js the glue). The QWebEnginePage is the page (the logic, the runJavaScript, the profile), and the QWebEngineView is the widget (the display) - the two are the web content: the view the widget, the page the logic, and the runJavaScript the Python-to-JS the app uses.
The QWebChannel: The Two-Way Bridge
from PyQt5.QtWebChannel import QWebChannel
from PyQt5.QtCore import QObject, pyqtSlot, QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWidgets import QApplication, QLabel
import sys
app = QApplication(sys.argv)
# the PYTHON object (the JS callable, the slots)
class Bridge(QObject):
@pyqtSlot(str, result=str)
def greet(self, name):
return "the hello, " + name
@pyqtSlot(str)
def log(self, message):
print("the js said:", message)
bridge = Bridge()
channel = QWebChannel()
channel.registerObject("bridge", bridge) # the name the
# JS references (the qwebchannel.js glue below)
view = QWebEngineView()
view.page().setWebChannel(channel) # the page channel
# the html: the qwebchannel.js + the bridge call
html = """
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
<script>
new QWebChannel(qt.webChannelTransport, function() {
window.bridge.log("the from the js");
window.bridge.greet("world").then(r =>
document.body.textContent = r);
});
</script>
"""
view.setHtml(html, QUrl("https://local/"))
view.show()
sys.exit(app.exec_())
The QWebChannel is the two-way bridge: the Python QObject (the Bridge with its @pyqtSlot - the greet the result the return, the log the void), the registerObject (the name the JS references), and the setWebChannel (the page's channel). The qwebchannel.js (the qrc:///qtwebchannel/qwebchannel.js - the resource system's, the previous chapter) is the glue: the new QWebChannel(qt.webChannelTransport, callback) in the JS, and the window.bridge is the Python object (the bridge.log the call to the Python's log slot, the bridge.greet the promise the result). The two-way is the point: the Python calls the JS (the runJavaScript), and the JS calls the Python (the QWebChannel the @pyqtSlot) - the hybrid's full bridge, the web content and the native logic talking both ways, and the @pyqtSlot the Python's the JS-callable.
The Working Rules
- The
QWebEngineViewis the web content as theQWidget. Theload(QUrl)the network (the async, theloadFinished), thesetHtmlthe inline, and the view is the central widget or the child - the native frame (theQMainWindow, the toolbar) is the Qt's, the content is the web's, and thetitleChangedis the bridge from the web to the native title. - The
runJavaScriptis the Python-to-JS, the callback the result. Thepage.runJavaScript(js, callback)is theevalof the JS, the callback the result (the async, the event loop's) - the one-way bridge the app uses to drive the web content from the Python. - The
QWebChannelis the two-way, the@pyqtSlotthe JS-callable. TheregisterObject(the name), thesetWebChannel(the page's), and theqwebchannel.js(the resource, theqrc:///qtwebchannel/qwebchannel.js) the glue - thewindow.bridgeis the Python object, and thebridge.slotthe JS's call to the Python. - The
QWebEnginePageis the logic, theQWebEngineViewis the display. ThesetPagethe custom page (therunJavaScript, theprofilethe storage), and the view is the widget - the two are the web content, and theprofileis the per-app storage (the cookies, thelocalStorage, the cache). - The
qwebchannel.jsis the resource, theqrc:///path. Theqtwebchannel.jsis bundled (theqrc:///qtwebchannel/qwebchannel.js), and thesetHtml's base url is thehttps://local/(theqrcresolves) - the resource system's chapter applies, and theQWebChannelneeds theqwebchannel.jsloaded in the page.
Summary
The QtWebEngine module embeds the Chromium engine in the Qt app: the QWebEngineView is the web content as the QWidget (the load(QUrl) the async network, the setHtml the inline, the titleChanged the bridge to the native title, the loadFinished the completion), and the QWebEnginePage is the page's logic (the runJavaScript the Python-to-JS with the callback the result, the profile the storage). The QWebChannel is the two-way bridge: the Python QObject (the @pyqtSlot the JS-callable, the result the return), the registerObject (the name), the setWebChannel (the page's), and the qwebchannel.js (the qrc:///qtwebchannel/qwebchannel.js resource) the glue - the window.bridge is the Python object, and the bridge.slot the JS's call to the Python. The hybrid is the point: the native frame (the QMainWindow, the toolbar, the status bar) is the Qt's, the content is the web's, and the runJavaScript plus the QWebChannel are the two-way bridge the web content and the native logic use to talk.