How can I embed plotly graphs (offline) in my PyQt application?

I want to embed plotly python graph in my PyQt application for working in desktop UI.

Is there any way?

Thanks in advance.

Plotly is a web based plotting library. So using web views immediately springs to mind, which would create a convoluted architecture of code.

I would suggest considering Dash further for your whole application, which can run locally.

Or you could use matplotlib with some drop down widgets to drive the visuals.

1 Like

hey @nasirfardoush ,
have you found a way? I want to implement a gauge in my pyqt application.
any help is appreciated.

Sorry, no way found with Plotly.
I have done my work using matplotlib instead of Plotly.js

1 Like

I know this is late to the party, but I’ve just found a work around.

I took advantage of the QWebEngineView()'s load() function to load an offline HTML file. In this case, I successfully loaded a fully interactive Plotly figure using this method.

import plotly.express as px
import PySide6  # version 6.9.1
from PySide6 import QtWidgets, QtCore, QtGui, QtWebEngineWidgets

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.main_widget = QtWidgets.QFrame()
        self.main_layout = QtWidgets.QVBoxLayout()  # could be whatever layout you want

        self.file_path = os.path.join(os.getcwd(), "plot.html")   # saves Plotly figure as "plot.html"
        self.browser = QtWebEngineWidgets.QWebEngineView()
        self.update_plotly_figure()

        self.main_widget.setLayout(self.main_layout)
        self.setCentralWidget(self.main_widget)

        self.setWindowTitle("Plotly in Qt Offline")
    
    def update_plotly_html(self, fig: Figure):
        html = fig.to_html()
        with open(self.file_path, "w", encoding="utf-8") as f:
            f.write(html)
    
    def update_browser_contents(self, fig: Figure):
        self.update_plotly_html(fig)
        url = QtCore.QUrl.fromLocalFile(self.file_path)
        self.browser.load(url)  # this is where the magic happens
    
    def update_plotly_figure(self):
        data = px.data.iris()
        fig = px.scatter(data, x="sepal_length", y="petal_length", color="species")
        fig = fig.update_layout(title="Sepal Length vs Petal Length", xaxis_title="Sepal Length", yaxis_title="Petal Length")
        self.update_browser_contents(fig)


if __name__ == "__main__":
    app = QtWidgets.QApplication([])

    widget = MainWindow()
    widget.show()

    exit(app.exec())

Here is a step-by-step break down of what happens:

  1. Create Plotly figure
  2. Save figure HTML to local file
  3. Read local HTML file as QUrl using QUrl.fromLocalFile()
  4. Load QUrl object into QWebEngineView() using the load() method

This method is a little slower than the online version, but it works just the same. All interactivity is retained using this method.