【问题标题】:Give data to a ChartView (LineSeries) - QML将数据提供给 ChartView (LineSeries) - QML
【发布时间】:2018-01-18 18:10:59
【问题描述】:

我最近开始使用 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)
    ...
}

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

是否有我正在监督的优雅解决方案?

【问题讨论】:

  • 为什么不用QAbstractListmodel?
  • @eyllanesc 我从未使用过 QAbstractListmodel,但我不知道这将如何解决我的问题...
  • 你需要使用QMap吗?为什么要使用 QMap?

标签: c++ qt qml


【解决方案1】:

我已经使用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])
        }
    }
    ...
}

【讨论】:

    【解决方案2】:

    我记得 QML 中的 Javascript 仅使用 QVariantList 和 QVariantMap 与 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;
    };
    

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

    使用这种方式可以为您带来一些额外的优势,例如数据变化信号等。

    【讨论】:

    • 你为什么说QVariantMap对我没有好处?因为现在,我正在尝试实现它,并且看起来它会起作用!
    • 好的,如果你说QVariantMap 对你有好处,我很高兴。我的意思是 QVariantMap 与 QMap&lt;QString, QVariant&gt; 相同,因此您在使用这些类型时受到限制。我展示的自定义实现不会限制您的类型。
    • 是否可以直接将 QLineSeries 作为属性从 c++ 公开到 QML?这样系列就不必在 JS 中构建了。
    猜你喜欢
    • 1970-01-01
    • 2017-09-10
    • 2011-04-30
    • 1970-01-01
    • 2018-05-05
    • 2018-05-23
    • 1970-01-01
    • 1970-01-01
    • 2018-06-19
    相关资源
    最近更新 更多