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

时间:2018-01-15 10:31:03

标签: c++ qt qml

我最近开始使用QML,我正在寻找一种方法,用QML将数据从c ++提供给我的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"
    }
}

robot.h:

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

main.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();
}

我有监督的优雅解决方案吗?

2 个答案:

答案 0 :(得分:1)

我已使用QVariantMap解决了这个问题。它不是最优雅的解决方案,但它的工作原理:) 我的QML文件中有一个javascript函数可以填充lineseries。 此功能连接到我的机器人信号,当新数据到达时将发送该信号。

robot.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])
        }
    }
    ...
}

答案 1 :(得分:0)

我记得QML中的Javascript只使用QVariantListQVariantMap来运行C ++数组。正如我所见,它们对你都不好。因此,我建议您以您喜欢的方式将您的地图存储在C ++中,并提供一些方便的方法来访问这些值。例如,使用singleton:

<强> 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;
};

<强> mysingleton.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;
}

注册(main.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));
            }
        }
    }
}

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