Search code examples
pythonpyqtpyqt5plotlyqwebengineview

Using a local file in html for a PyQt5 webengine


I am trying to embed a plotly graph into a PyQt5 webengine view. I was able to do so using the following:

open plotly in qwebview in interactive mode

If you read it, the article explains that you can't directly include the javascript in the HTML when using the webengine view (it has issues loading files above 2 MB). However, I'm trying to make it so that the source for the javascript is a local copy of plotly-min.js (saved in the project folder) so that anyone using the program doesn't need an internet connection to view the graphs it generates. I've tried to follow a few examples on html, but to no avail.

The original code that does work with an internet connection is:

raw_html = '<html><head><meta charset="utf-8" />'
raw_html += '<script src="https://cdn.plot.ly/plotly-latest.min.js"></script></head>'
raw_html += '<body>'
raw_html += plot(fig, include_plotlyjs=False, output_type='div')
raw_html += '</body></html>'

temp_view = QWebEngineView()
temp_view.setHtml(graph)

If I understand it correctly, I need to change this part:

<script src="https://cdn.plot.ly/plotly-latest.min.js">

I've already tried:

<script type="text/javascript" src="file:///C:/Users/UserName/PycharmProjects/ProjectFolder/plotly-latest.min.js"></script>

I honestly do not know HTML. This is the only HTML in the code (the rest is in Python 3). Does anyone know why the above might not work and what I need to change? I have a suspicion I might somehow be running into the 2 MB limit the above question referenced, as different variations I've found online for how to reference a local file in HTML don't seem to change anything.


Solution

  • Many browsers for security reason disable the loading of local files, but as noted in the following forum you can enable that capability with:

    sys.argv.append("--disable-web-security")
    

    Assuming the .js is next to your .py file:

    .
    ├── main.py
    └── plotly-latest.min.js
    

    you can use the following example:

    import sys
    from PyQt5.QtWidgets import QApplication
    from PyQt5.QtWebEngineWidgets import QWebEngineView
    from PyQt5.QtCore import QDir, QUrl
    
    import plotly
    import plotly.graph_objs as go
    
    sys.argv.append("--disable-web-security")
    app = QApplication(sys.argv)
    
    x1 = [10, 3, 4, 5, 20, 4, 3]
    trace1 = go.Box(x = x1)
    layout = go.Layout(showlegend = True)
    data = [trace1]
    
    fig = go.Figure(data=data, layout = layout)
    
    path = QDir.current().filePath('plotly-latest.min.js') 
    local = QUrl.fromLocalFile(path).toString()
    
    raw_html = '<html><head><meta charset="utf-8" />'
    raw_html += '<script src="{}"></script></head>'.format(local)
    raw_html += '<body>'
    raw_html += plotly.offline.plot(fig, include_plotlyjs=False, output_type='div')
    raw_html += '</body></html>'
    
    view = QWebEngineView()
    view.setHtml(raw_html)
    view.show()
    
    sys.exit(app.exec_())
    

    enter image description here