[Python] QWebEngineView renders bokeh vizualisation with largish data (~18000 points) slowly

Discussão em 'Python' iniciado por Stack, Setembro 23, 2024.

  1. Stack

    Stack Membro Participativo

    I'm trying to include a Bokeh based visualisation canvas in a Qt application written in Python (using PySide6). So I create the visualisation, save it in an HTML file, and read it in a QWebEngineView widget. It renders fine, but is extremely sluggish to interact with it; e.g. try selecting the zoom tool and zooming in, or panning. The surprising part is, when I open the same HTML in Firefox, it is pretty snappy, as I would expect.

    There are 2 time series, with 8760 data points each in the plot. What is going on here?

    Minimal example


    from argparse import ArgumentParser
    from pathlib import Path


    from PySide6.QtCore import QUrl, QSize
    from PySide6.QtWidgets import QApplication, QMainWindow
    from PySide6.QtWebEngineWidgets import QWebEngineView


    class MainWindow(QMainWindow):
    def __init__(self, path: str = "", *args, **kwargs):
    super().__init__(*args, **kwargs)

    if path:
    self.browser = QWebEngineView()
    self.browser.setUrl(QUrl.fromLocalFile(Path(path).absolute()))
    self.setCentralWidget(self.browser)
    self.resize(QSize(800, 500))


    if __name__ == "__main__":
    # HTML example produced using Bokeh: dump-viz.html
    parser = ArgumentParser()
    parser.add_argument("file")
    opts = parser.parse_args()

    app = QApplication()
    window = MainWindow(opts.file)
    window.show()
    app.exec()


    The above script, and an example HTML is available in this gist.

    You can run it with hatch run pyside-qwebengine-slow.py qwebengine-ex-viz.html, or create a virtual env, then pip install PySide6, and run normally.

    Additional info


    The code that I use to generate that plot, is more or less equivalent to:

    def make_plot(data_list)
    """`data_list`: list of dataclasses representing a time series;
    data.y, data.labels, etc.
    """
    palette = TolRainbow[10]
    legend_items = {}
    fig = figure(x_axis_label="x_label", y_axis_label="y_label", title="title", height=400, width=800)
    for idx, data in enumerate(data_list):
    df = pd.DataFrame({y_label: data.y})
    line = fig.line("index", "y_label", source=df, color=palette[idx])
    point = fig.scatter("index", "y_label", source=df, color=palette[idx], size=7)
    legend_items[data.labels[0]] = [line, point]

    legend = Legend(items=list(legend_items.items()))
    fig.add_layout(legend, "right")
    fig.legend.click_policy = "hide"
    return fig

    fig = make_plot(data_list)
    html = file_html(fig, INLINE, title)

    Continue reading...

Compartilhe esta Página