cannot change backgroundImage using QWebEnginePage::runJavaScript()

Viewed 681

I originally want to solve this problem , but as I have tested the behavior of QWebEnginePage::runJavaScript() , I found I cannot even change the backgroundImage using QWebEnginePage::runJavaScript() with the following code, so why ?

import sys

from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtWebEngineCore import *


class WebEngineView(QWebEngineView):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.webPage = self.page()
        # self.webPage = WebEnginePage()
        self.webPage.load(QUrl('https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style'))
        self.webPage.runJavaScript('''
                                window.addEventListener("load", function(event) {
                                        alert(document.title);
                                        document.body.style.backgroundImage = "url('https://www.w3schools.com/jsref/img_tree.png')";

                                });
                     ''')  # QWebEngineScript.MainWorld


if __name__ == "__main__":

    app = QApplication(sys.argv)
    app.setAttribute(Qt.AA_UseSoftwareOpenGL)
    webEngineView = WebEngineView()
    webEngineView.show()
    sys.exit(app.exec_())
1 Answers

You want to modify the DOM so this must be already created, in your case you use runJavaScript before the page is loaded and the DOM is not built. Considering that there are 2 possible solutions:

  • Use the loadFinished signal to execute the script after loading the page:
import sys
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets


class WebEngineView(QtWebEngineWidgets.QWebEngineView):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.loadFinished.connect(self.on_load_finished)

        self.load(
            QtCore.QUrl(
                "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style"
            )
        )

    @QtCore.pyqtSlot(bool)
    def on_load_finished(self, ok):
        if ok:
            script = """
            alert(document.title);
            document.body.style.backgroundImage = "url('https://www.w3schools.com/jsref/img_tree.png')";
            """
            self.page().runJavaScript(script)


if __name__ == "__main__":
    QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_ShareOpenGLContexts)
    QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_UseSoftwareOpenGL)
    app = QtWidgets.QApplication(sys.argv)
    w = WebEngineView()
    w.show()
    sys.exit(app.exec_())
import sys

from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets


class WebEngineView(QtWebEngineWidgets.QWebEngineView):
    def __init__(self, parent=None):
        super().__init__(parent)

        script = QtWebEngineWidgets.QWebEngineScript()
        name = "test"
        source = """
        alert(document.title);
        document.body.style.backgroundImage = "url('https://www.w3schools.com/jsref/img_tree.png')";
        """
        script.setName(name)
        script.setSourceCode(source)
        script.setInjectionPoint(
            QtWebEngineWidgets.QWebEngineScript.DocumentReady
        )
        script.setRunsOnSubFrames(True)
        script.setWorldId(QtWebEngineWidgets.QWebEngineScript.ApplicationWorld)
        self.page().scripts().insert(script)

        self.load(
            QtCore.QUrl(
                "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style"
            )
        )


if __name__ == "__main__":
    QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_ShareOpenGLContexts)
    QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_UseSoftwareOpenGL)
    app = QtWidgets.QApplication(sys.argv)
    w = WebEngineView()
    w.show()
    sys.exit(app.exec_())
Related