将数据提供给 ChartView (LineSeries) - QML

Give data to a ChartView (LineSeries) - QML

本文关键字:LineSeries QML ChartView 数据      更新时间:2023-10-16

我最近开始使用QML,我正在寻找一种将数据从c ++提供给QML中的ChartView的方法。我更喜欢一个解决方案,我可以发送类似 Q_PROPERTY 的 QMap,以便它自动更新。

我搜索并发现您可以执行一个函数,然后您可以使用"append(("向图表添加值。但我似乎无法向 QML 发送某种列表......

QML 文件:

ChartView {
    theme: ChartView.ChartThemeQt
    antialiasing: true
    DateTimeAxis {
        id: dateTimeAxisX
    }
    ValueAxis{
        id: valueAxisY
        min: 0
        max: 15
        titleText: "Voltage (V)"
    }
    LineSeries {
        id: voltageSeries
        axisX: dateTimeAxisX
        axisY: valueAxisY
        name: "Battery Voltage"
    }
}

机器人.h:

class Robot: public QObject
{
    ...
    Q_PROPERTY(QMap<int, double> list_battery_voltages READ getList_battery_voltages NOTIFY listBatteryVoltagesChanged)
    ...
}

主.cpp:

int main(int argc, char *argv[])
{
#if defined(Q_OS_WIN)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QApplication app(argc, argv);
    QQmlApplicationEngine engine;
    // Load custom class inside engine
    QScopedPointer<Robot> robot(new Robot(app.applicationDirPath() + "/robot_settings.ini"));
    engine.rootContext()->setContextProperty("robot", robot.data());
    QQmlComponent component(&engine, QUrl(QLatin1String("qrc:/main.qml")));
    component.create();
    return app.exec();
}

我正在监督哪些优雅的解决方案?

我已经使用 QVariantMap 解决了它。这不是最优雅的解决方案,但它:)我的 QML 文件中有一个 javascript 函数来填充行序列。此功能连接到我的机器人信号,当新数据到达时将发送该信号。

机器人.h:

class Robot: public QObject
{
    ...
    Q_PROPERTY(QVariantMap list_battery_voltages READ getList_battery_voltages NOTIFY listBatteryVoltagesChanged)
    ...
}

QML:

ChartView {
    ...
    Connections {
        target: robot
        onMapBatteryVoltagesChanged: insertVoltages()
    }
    Component.onCompleted: {
        insertVoltages()
    }
    ...
    function insertVoltages() {
        var voltages_map = robot.map_battery_voltages
        for (var prop in voltages_map) {
            voltageSeries.append(prop, voltages_map[prop])
        }
    }
    ...
}

记得QML中的Javascript仅使用QVariantListQVariantMap对数组C++进行操作。在我看来,它们对你都没有好处。因此,我建议您以您喜欢的方式将地图存储在C++中,并提供一些方便的方式来访问值。例如,使用单例:

Mysingleton.h

class MySingleton : public QObject
{
    Q_OBJECT
public:
    explicit MySingleton(QObject *parent = nullptr);
    Q_INVOKABLE int count();
    Q_INVOKABLE double getX(int index);
    Q_INVOKABLE double getY(int index);
private:
    QList<QPair<double, double>> m_map;
};

我的辛格尔顿.cpp

MySingleton::MySingleton(QObject *parent) : QObject(parent)
{
    QRandomGenerator *generator = QRandomGenerator::global();
    int count = generator->generate() % 10;
    double xAccumulated = 0;
    for(int i = 0;i < count;i ++)
    {
        double x = generator->generateDouble() / (double)count;
        xAccumulated += x;
        double y = generator->generateDouble();
        m_map.append(QPair<double, double>(xAccumulated, y));
    }
}
int MySingleton::count()
{
    return m_map.count();
}
double MySingleton::getX(int index)
{
    return m_map.at(index).first;
}
double MySingleton::getY(int index)
{
    return m_map.at(index).second;
}

注册(主要.cpp(:

static QObject *my_singleton_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
{   
    return new MySingleton(engine);
}
main() {
    qmlRegisterSingletonType<MySingleton>("Qt.MyTest", 1, 0, "MySingleton", my_singleton_provider);
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
}

所以现在你可以在QML中使用它:

import QtQuick 2.9
import QtCharts 2.1
import Qt.MyTest 1.0
ChartView {
    anchors.fill: parent
    LineSeries {
        id: series
        Component.onCompleted: {               
            for(var i = 0;i < MySingleton.count();i ++) {
                series.append(MySingleton.getX(i), MySingleton.getY(i));
            }
        }
    }
}

使用这种方式可以为您提供一些额外的优势,例如数据更改信号等。