Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Dynamically add point to LineSeries of QML Qt Graphs
Forum Updated to NodeBB v4.3 + New Features

Dynamically add point to LineSeries of QML Qt Graphs

Scheduled Pinned Locked Moved Solved QML and Qt Quick
8 Posts 3 Posters 944 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • W Offline
    W Offline
    Winz 0
    wrote on 2 Oct 2024, 20:41 last edited by
    #1

    I'd like to reproduce the same type of application as the Qml Oscilloscope example i.e. display real-time data on 2d line graph. Qml Oscilloscope is implemented using Qt Chart and I want to do the same but with Qt Graphs. This seems to be possible because the documentation says that "It's especially useful for visualizing depth maps and large quantities of rapidly changing data, such as data received from multiple sensors. " but looking at the LineSeries QML Type members and at all inherited members, there is no method to achieve this.

    Looking at header source of QXYSeries, which is the base class for QLineSeries you can read the following comment : "// TODO: Consider making these slots, available from QML." in front of all useful methods such as void append(qreal x, qreal y);

    I've derived a class from QLineSeries class to make this method invocable. This seems to work (I can add point to a LineSerie) but I haven't find how to refresh the GraphsView. I tried to call update on the graph and other stuff like this but with no results.

    I noticed that if you add points to a LineSerie and to stretch the main window, I can see the graph line for a second and the application crash immediately after.

    Do you have any ideas how to refresh the graph after adding points to SerialLines?

    Main.qml

    import QtQuick
    import QtGraphs
    import dynamicGraphs
    
    Window {
        width: 640
        height: 480
        visible: true
    
        property int range : 100
    
        Timer {
            interval: 500; running: true; repeat: true
            onTriggered: {
                mySerie.append(Math.round(2*range*Math.random())-range, Math.round(2*range*Math.random())-range)
                print(mySerie.count(), mySerie.points())
            }
        }
    
        GraphsView {
            id : graphs
            anchors.fill: parent
    
            // LineSeries {
            LineSeriesWrapper {
                id : mySerie
                color: "#00ff00"
                axisX: ValueAxis {
                    min : -range
                    max : range
                }
                axisY: ValueAxis {
                    min : -range
                    max : range
                }
                /*
                XYPoint { x: 0; y: 0 }
                   XYPoint { x: 1; y: 2.1 }
                   XYPoint { x: 2; y: 3.3 }
                   XYPoint { x: 3; y: 2.1 }
                   XYPoint { x: 4; y: 4.9 }
                   XYPoint { x: 5; y: 3.0 }
                   */
            }
        }
    }
    
    

    lineserieswrapper.h

    #ifndef LINESERIESWRAPPER_H
    #define LINESERIESWRAPPER_H
    
    #include <QLineSeries>
    
    class LineSeriesWrapper : public QLineSeries
    {
        Q_OBJECT
        QML_ELEMENT
    
    public:
        explicit LineSeriesWrapper(QObject *parent = nullptr);
        Q_INVOKABLE void append(qreal, qreal);
        Q_INVOKABLE int count();
        Q_INVOKABLE QList<QPointF> points();
    };
    
    #endif // QLINESERIESWRAPPER_H
    

    lineserieswrapper.cpp

    #include "lineserieswrapper.h"
    
    LineSeriesWrapper::LineSeriesWrapper(QObject *parent)
        : QLineSeries{parent}
    {}
    
    void LineSeriesWrapper::append(qreal x, qreal y)
    {
        QLineSeries::append(x, y);
    }
    
    int LineSeriesWrapper::count()
    {
        return QLineSeries::count();
    }
    
    QList<QPointF> LineSeriesWrapper::points()
    {
        return QLineSeries::points();
    }
    
    

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
        QObject::connect(
            &engine,
            &QQmlApplicationEngine::objectCreationFailed,
            &app,
            []() { QCoreApplication::exit(-1); },
            Qt::QueuedConnection);
        engine.loadFromModule("dynamicGraphs", "Main");
    
        return app.exec();
    }
    
    

    CMakeLists.txt

    cmake_minimum_required(VERSION 3.16)
    
    project(dynamicGraphs VERSION 0.1 LANGUAGES CXX)
    
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    
    find_package(Qt6 6.7 REQUIRED COMPONENTS Quick Graphs)
    
    qt_standard_project_setup(REQUIRES 6.7)
    
    qt_add_executable(appdynamicGraphs
        main.cpp
    )
    
    qt_add_qml_module(appdynamicGraphs
        URI dynamicGraphs
        VERSION 1.0
        QML_FILES
        Main.qml
        SOURCES
        lineserieswrapper.h lineserieswrapper.cpp
    )
    
    # Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
    # If you are developing for iOS or macOS you should consider setting an
    # explicit, fixed bundle identifier manually though.
    set_target_properties(appdynamicGraphs PROPERTIES
        #    MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appdynamicGraphs
        MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
        MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
        MACOSX_BUNDLE TRUE
        WIN32_EXECUTABLE TRUE
    )
    
    target_link_libraries(appdynamicGraphs
        PRIVATE Qt6::Quick Qt6::Graphs
    )
    
    include(GNUInstallDirs)
    install(TARGETS appdynamicGraphs
        BUNDLE DESTINATION .
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    )
    
    
    1 Reply Last reply
    0
    • B Offline
      B Offline
      Bob64
      wrote on 2 Oct 2024, 22:02 last edited by
      #2

      There was a similar question about this the other day that I looked at. I am not even on Qt6 yet so the following is just from my understanding of the docs and what I know of using QtCharts. The code below is very sketchy and is just to give the idea.

      I think you are heading in the right direction that you need to do the update from C++. However, I don't think you should derive from QLineSeries. Instead, create a LineSeries in QML and expose a different C++ class (let's call it DataSource) to QML that provides an appendToSeries function. This should take a QLineSeries* as an argument. In the implementation of appendToSeries you will have full access to the QLineSeries public API.

      In the following I have assumed that DataSource is registered as a "singleton instance":

          Timer {
              interval: 500; running: true; repeat: true
              onTriggered: {
                  DataSource.appendToSeries(mySerie, Math.round(2*range*Math.random())-range, Math.round(2*range*Math.random())-range)
                  print(mySerie.count(), mySerie.points())
              }
          }
          GraphsView {
              id : graphs
              anchors.fill: parent
      
              LineSeries {
                  id : mySerie
                  color: "#00ff00"
                  axisX: ValueAxis {
                      min : -range
                      max : range
                  }
                  axisY: ValueAxis {
                      min : -range
                      max : range
                  }
              }
          }
      
      1 Reply Last reply
      0
      • W Offline
        W Offline
        Winz 0
        wrote on 4 Oct 2024, 06:28 last edited by
        #3

        I've seen several posts on this subject but haven't found a satisfactory solution. The only thing that seems to work is to delete and re-instantiate the entire LineSerie each time a point is added, but I haven't succeeded.

        I've implemented your suggestion but the result is the same: the points are added, the GraphicsView remains empty and if I stretch the windows, I can see the graphic for a second and the application crash.

        1 Reply Last reply
        0
        • B Offline
          B Offline
          Bob64
          wrote on 4 Oct 2024, 07:36 last edited by
          #4

          OK - my suggestion was essentially the same as the approach taken in the Oscilloscope example. If that isn't working, I am sorry but I don't have anything else to suggest. Perhaps it is simply that there are some limitations with QtGraphs at the moment.

          You could maybe try joining the "Qt Interest" mailing list (https://lists.qt-project.org/listinfo/interest) and asking there.

          1 Reply Last reply
          0
          • W Offline
            W Offline
            Winz 0
            wrote on 4 Oct 2024, 11:16 last edited by
            #5

            Yes, I will. I understand that QtGraphs is intended to replace QtCharts and Qt Data Visualization, so we can expect at least the same functionality.

            1 Reply Last reply
            0
            • B Offline
              B Offline
              Bob64
              wrote on 4 Oct 2024, 11:25 last edited by
              #6

              Yes, I would hope so anyway. I assume they will deprecate QtCharts at some point so I hope the replacement is working by the time I have to make the switch!

              1 Reply Last reply
              0
              • W Offline
                W Offline
                Winz 0
                wrote on 7 Oct 2024, 20:26 last edited by
                #7

                It's okay, it fixed itself !
                The move to Qt6.8 has taken QtGraphs out of Technology Preview status, and functions like append(x,y) that weren't accessible in QML now are.

                1 Reply Last reply
                1
                • W Winz 0 has marked this topic as solved on 7 Oct 2024, 20:26
                • D Offline
                  D Offline
                  duojiaoyutouteng
                  wrote on 15 Oct 2024, 09:07 last edited by
                  #8
                  This post is deleted!
                  1 Reply Last reply
                  0

                  1/8

                  2 Oct 2024, 20:41

                  • Login

                  • Login or register to search.
                  1 out of 8
                  • First post
                    1/8
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved