自定义或定义新的 Qml ChartView 主题

Customize or Define new Qml ChartView theme

官方有自定义QChart背景和绘图区画笔的示例代码:Custom chart example

如何使用 ChartView(Qml 类型)以 Qml 方式实现此目的?

我想像那个示例一样自定义 Qml ChartView。但是没有直接的方法(qml 属性)从 qml 更改画笔。 ChartView.ChartTheme 属性 也是用 C++ 预定义和硬编码的。我不知道它是否可能以及如何继承 QChart 以从 C++ 更改这些属性并定义自定义 QML 类型。

并非 Qt Charts C++ 中的所有可修改属性在 QML 中都是可修改的,尽管可以通过使用 findChild 和 items 进行过滤来访问 QChart。

也可以用类似的方式修改一些未公开的轴属性。

#include <QtQuick>
#include <QtWidgets>
#include <QtCharts>

class Helper: public QObject
{
    Q_OBJECT 
public:
    Q_INVOKABLE void update_chart(QQuickItem *item){
        if(QGraphicsScene *scene = item->findChild<QGraphicsScene *>()){
            for(QGraphicsItem *it : scene->items()){
                if(QtCharts::QChart *chart = dynamic_cast<QtCharts::QChart *>(it)){
                    // Customize chart background
                    QLinearGradient backgroundGradient;
                    backgroundGradient.setStart(QPointF(0, 0));
                    backgroundGradient.setFinalStop(QPointF(0, 1));
                    backgroundGradient.setColorAt(0.0, QRgb(0xd2d0d1));
                    backgroundGradient.setColorAt(1.0, QRgb(0x4c4547));
                    backgroundGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
                    chart->setBackgroundBrush(backgroundGradient);
                    // Customize plot area background
                    QLinearGradient plotAreaGradient;
                    plotAreaGradient.setStart(QPointF(0, 1));
                    plotAreaGradient.setFinalStop(QPointF(1, 0));
                    plotAreaGradient.setColorAt(0.0, QRgb(0x555555));
                    plotAreaGradient.setColorAt(1.0, QRgb(0x55aa55));
                    plotAreaGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
                    chart->setPlotAreaBackgroundBrush(plotAreaGradient);
                    chart->setPlotAreaBackgroundVisible(true);
                }
            }
        }
    }
    Q_INVOKABLE void update_axes(QtCharts::QAbstractAxis *axisX, QtCharts::QAbstractAxis *axisY){
        if(axisX && axisY){
            // Customize axis colors
            QPen axisPen(QRgb(0xd18952));
            axisPen.setWidth(2);
            axisX->setLinePen(axisPen);
            axisY->setLinePen(axisPen);
            // Customize grid lines and shades
            axisY->setShadesPen(Qt::NoPen);
            axisY->setShadesBrush(QBrush(QColor(0x99, 0xcc, 0xcc, 0x55)));
        }
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);    
    QApplication app(argc, argv);
    QQmlApplicationEngine engine;
    Helper helper;
    engine.rootContext()->setContextProperty(QStringLiteral("helper"), &helper);
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);
    return app.exec();
}
#include "main.moc"
import QtQuick 2.13
import QtQuick.Controls 2.13

import QtCharts 2.0

ApplicationWindow {
    id: root
    visible: true
    width: 640
    height: 480
    ChartView {
        id: view
        anchors.fill: parent
        title: "Customchart example"
        titleColor: "white"
        titleFont.pixelSize: 18
        antialiasing: true
        LineSeries{
            axisX: CategoryAxis {
                id: xaxis
                min: 0
                max: 30
                labelsFont.pixelSize: 12
                gridVisible: false
                labelsColor: "white"
                CategoryRange {
                    label: "low"
                    endValue: 10
                }
                CategoryRange {
                    label: "optimal"
                    endValue: 20
                }
                CategoryRange {
                    label: "high"
                    endValue: 30
                }
            }
            axisY: CategoryAxis {
                id: yaxis
                min: 0
                max: 30
                labelsFont.pixelSize: 12
                gridVisible: false
                labelsColor: "white"
                shadesVisible: true
                CategoryRange {
                    label: "slow"
                    endValue: 10
                }
                CategoryRange {
                    label: "med"
                    endValue: 20
                }
                CategoryRange {
                    label: "fast"
                    endValue: 30
                }
            }
            color: "#fdb157"
            width: 5
            XYPoint { x: 0; y: 6 }
            XYPoint { x: 9; y: 4 }
            XYPoint { x: 15; y: 20 }
            XYPoint { x: 25; y: 12 }
            XYPoint { x: 29; y: 26 }
        }
        Component.onCompleted: {
            view.legend.visible = false
            helper.update_chart(view)
            helper.update_axes(xaxis, yaxis)
        }
    }
}