2

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_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
iMath
  • 2,326
  • 2
  • 43
  • 75

1 Answers1

4

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_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thank you ! It works ! I tried to inject a web page progress bar to a webpage using QWebEnginePage::runJavaScript() with almost the same code logic , but it failed , can you give a help https://forum.qt.io/topic/103975/inject-code-to-webpage-using-qwebenginepage-runjavascript ? Thanks ! – iMath Jun 18 '19 at 14:14
  • @iMath I do not know what that code does, it would have to take me more time to analyze it but if it does the same as your previous question it will not work. The problem with your previous question is that you should load the script right into the creation of the DOM to measure the progress, but in my current response is measured when I finish the process of loading the DOM so there is nothing to measure, why it fails. – eyllanesc Jun 18 '19 at 15:45
  • I have followed your answer and changed my code to set webEngineScript.setInjectionPoint(QWebEngineScript.DocumentReady) related stuff in my previous question , I guess the current problem is about JavaScript and QWebEngineScript. I was stuck here for not knowing much about JS. – iMath Jun 19 '19 at 01:45