【问题标题】:How to render Altair / Vega in a PyQt widget如何在 PyQt 小部件中渲染 Altair / Vega
【发布时间】:2020-02-13 14:23:16
【问题描述】:

是否可以让 Altair 或 Vega(-Lite) 渲染到 PyQt 小部件,类似于支持多个后端的 Matplotlib?我知道我可以使用 Qt WebView 小部件来呈现带有 Vega-embed 的网页,但我想避免必须提供此服务的开销,即使在本地也是如此。

【问题讨论】:

    标签: pyqt vega vega-lite altair


    【解决方案1】:

    使用 Altair 可视化绘图的最佳选择是使用 QWebEngineView,因为 altair 可以根据您设置的指令创建 javascript 代码。恕我直言,最好的解决方案是获取图表的 html 并将其设置在 QWebEngineView 中。在下面的示例中,我展示了如何执行上述操作,此外还启用了将图像保存为 svg 或 png 等特性。

    from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
    
    from io import StringIO
    
    
    class WebEngineView(QtWebEngineWidgets.QWebEngineView):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.page().profile().downloadRequested.connect(self.onDownloadRequested)
            self.windows = []
    
        @QtCore.pyqtSlot(QtWebEngineWidgets.QWebEngineDownloadItem)
        def onDownloadRequested(self, download):
            if (
                download.state()
                == QtWebEngineWidgets.QWebEngineDownloadItem.DownloadRequested
            ):
                path, _ = QtWidgets.QFileDialog.getSaveFileName(
                    self, self.tr("Save as"), download.path()
                )
                if path:
                    download.setPath(path)
                    download.accept()
    
        def createWindow(self, type_):
            if type_ == QtWebEngineWidgets.QWebEnginePage.WebBrowserTab:
                window = QtWidgets.QMainWindow(self)
                view = QtWebEngineWidgets.QWebEngineView(window)
                window.resize(640, 480)
                window.setCentralWidget(view)
                window.show()
                return view
    
        def updateChart(self, chart, **kwargs):
            output = StringIO()
            chart.save(output, "html", **kwargs)
            self.setHtml(output.getvalue())
    
    
    if __name__ == "__main__":
        import sys
    
        import altair as alt
        from vega_datasets import data
    
        app = QtWidgets.QApplication(sys.argv)
        w = QtWidgets.QMainWindow()
    
        cars = data.cars()
    
        chart = (
            alt.Chart(cars)
            .mark_bar()
            .encode(x=alt.X("Miles_per_Gallon", bin=True), y="count()",)
            .properties(title="A bar chart")
            .configure_title(anchor="start")
        )
    
        view = WebEngineView()
        view.updateChart(chart)
        w.setCentralWidget(view)
        w.resize(640, 480)
        w.show()
        sys.exit(app.exec_())
    

    【讨论】:

      【解决方案2】:

      目前 Altair 唯一的渲染后端是 Vega-Embed,因此在 PyQt 小部件中渲染它需要运行一些 Javascript 引擎。我怀疑 Qt WebView 可能是最好的选择。

      如果您不介意失去图表的交互性,您还可以使用altair_saver 作为后端来存储图表的静态 PNG、SVG 或 PDF 并将其显示在 QtWidget 中。

      【讨论】:

        猜你喜欢
        • 2021-01-20
        • 2019-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-24
        • 2015-12-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多