将 QML 的 ChartView 保存到 PyQt5 中的图像文件

Saving QML's ChartView to image file in PyQt5

我的方法大致是这样的:

Chart.qml:

Window {
    ChartView {
        id: chartView
        // ...
    }

    Button {
        text: "save"
        onClicked: manager.save(chartView)
    }
}

Manager.py:

class Manager(QObject):
    @pyqtSlot(QObject)
    def save(self, chartview):
        img = chartview.grab()
        img.save(MY_DEFAULT_PATH)

当然,问题在于 Manager.save() 中的图表视图等同于没有 'grab' 方法的 C++ QObject*。但它可以向下转换为 QChartView*(或至少 QWidget*),这种方法具有。在 C++ 中,我可能会使用 qobject_cast.

我的问题是:

  1. 这种向下转换在 PyQt 中可行吗?
  2. 如果没有 - 您知道如何以不同的方式完成吗?

在给出答案之前,最好澄清一下 post 的一些错误:

  • QML ChartView 是一个 Item,与 QChartView 不同,QChartView 是一个 QWidget。该项目是使用来自 QGraphicsScene 和 QChart 的信息绘制的。考虑到上述情况,一种方法可能是访问 QGraphicsScene 和 QChart,并使用 QGraphicsScene 的 render() 方法。

  • 您可以通过 sip.cast() 方法使用 sip 进行转换。

  • 在这种情况下,也没有必要进行向下转换,因为在签名中表明就足够了:

class Manager(QtCore.QObject):
    @QtCore.pyqtSlot(QtQuick.QQuickItem)
    def save(self, chartview):
        self.result = chartview.grabToImage()

        def handle_ready():
            self.result.saveToFile(MY_DEFAULT_PATH)
            delattr(self, "result")

        self.result.ready.connect(handle_ready)

但是您可以使用 grabToImage 方法而不是变得太复杂,因为它是一个项目:

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtCharts 2.2

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    Button {
        id: btn
        text: "Save"
        anchors.top: parent.top
        onClicked: saveChart("chart.png") 
    }
    ChartView {
        id: chartView
        anchors.top: btn.bottom
        width: parent.width
        anchors.bottom: parent.bottom
        LineSeries {
            XYPoint { x: 0; y: 0 }
            XYPoint { x: 1.1; y: 2.1 }
        }
    }

    function saveChart(filename){
        chartView.grabToImage(function(result) {
            result.saveToFile(filename);
        });
    }   
}