2

I have a string obtained from rendering a Jinja template. In the template I have the absolute path to the css file. For example:

<link rel='stylesheet' href="C:\Users\User\project\reports\template\css">

But, when I set the html in QWebEngineView only appear the plain HTML, without CSS. How can I make to detect the css reference?

This is my code

class WidgetEdificioCirsoc(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        self._tab_edificio = widgets.TabEdificio()
        self._webview = QtWebEngineWidgets.QWebEngineView()
        layout_horizontal_principal = QtWidgets.QHBoxLayout()
        layout_horizontal_principal.addWidget(self._tab_edificio)
        layout_horizontal_principal.addWidget(self._webview)
        self.setLayout(layout_horizontal_principal)

    def calcular(self):
        edificio = self._tab_edificio()
        reporte = edificio.reporte.html() # Generate the string
        self._webview.setHtml(reporte) # Set the string
7
  • 1
    Could you please provide a minimal reproducible example Commented Jul 17, 2018 at 18:56
  • Off course, I updated my question. Commented Jul 17, 2018 at 19:00
  • @Eduardo. Loading of local files is prevented as a security feature. You need to serve the files from a local web-server. To do this, run python3 -m http.server. Files are then served relative to the directory where the server was started. So if you start the server in "C:\Users\User\project\reports", your urls will need to look like this: http://localhost:8000/template/filename.css. Commented Jul 17, 2018 at 21:30
  • @ekhumoro Thaks for the response. I thought it would be an easier procedure. Because when I load an html file, the css is loaded too. For example: self._webview.load(QtCore.QUrl.fromLocalFile(r'C:\Users\User\project\reports\template\test.html')) Commented Jul 18, 2018 at 10:18
  • 1
    @Eduardo. Yes, it's really a bug in setHtml that is triggering the security feature - see QTBUG-52085. It looks like a fix was attempted at some point but it was backed out because it caused other problems. I suppose the simplest work-around would be to write a temporary file for the html and then call load instead. Commented Jul 18, 2018 at 11:22

1 Answer 1

2

QWebEngineView when you use setHtml() method does not handle the urls, a workaround is to load the css using javascript as shown below:

.
├── main.py
└── css
    └── styles.css

main.py

from PyQt5 import QtWebEngineWidgets, QtWidgets, QtCore

def loadCSS(view, path, name):
    path = QtCore.QFile(path)
    if not path.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text):
        return
    css = path.readAll().data().decode("utf-8")
    SCRIPT = """
    (function() {
    css = document.createElement('style');
    css.type = 'text/css';
    css.id = "%s";
    document.head.appendChild(css);
    css.innerText = `%s`;
    })()
    """ % (name, css)

    script = QtWebEngineWidgets.QWebEngineScript()
    view.page().runJavaScript(SCRIPT, QtWebEngineWidgets.QWebEngineScript.ApplicationWorld)
    script.setName(name)
    script.setSourceCode(SCRIPT)
    script.setInjectionPoint(QtWebEngineWidgets.QWebEngineScript.DocumentReady)
    script.setRunsOnSubFrames(True)
    script.setWorldId(QtWebEngineWidgets.QWebEngineScript.ApplicationWorld)
    view.page().scripts().insert(script)


HTML = """
<!DOCTYPE html>
<html>
<head>
</head>
<body>

<h1>I am formatted with a style sheet</h1>
<p>Me too!</p>

</body>
</html>
"""

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    view = QtWebEngineWidgets.QWebEngineView()
    view.setHtml(HTML, QtCore.QUrl("index.html"))

    loadCSS(view, "css/styles.css", "script1")

    view.show()
    sys.exit(app.exec_())

css/styles.css

body {
    background-color: lightblue;
}

h1 {
    color: white;
    text-align: center;
}

p {
    font-family: verdana;
    font-size: 20px;
}

enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! I'll try it.
1) I have tested removing repaint and it works correctly (I use linux). 2) There is a well-known bug in Qt that affects MacOS that makes it necessary to call repaint unfortunately and there is still no solution, perhaps in future releases it will be fixed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.