Moving charts in Chartview



  • Hello, I am wondering if it is possible to have moving charts in Chartview. The X-axis can be time and new data is appended in every new second. The data feeding the series from the C++. Instead of replacing entire series, is it possible to just shift the data in the series for performance.


  • Qt Champions 2017

    Did you get a chance to look at the chart directory under examples in Qt Installation ? I remember seeing the examples of moving chart. It should help you.



  • Yup. I like your thinking. That's what I did, instead of rapidly update my data I update just an date time axis.

    Have 2 axis. Move ones range with time... I have an DateTimeAxis, with an invisible LineSeries with a single {0,0} point.

    The rest of my LineSeries as normal.

    I also do crimes against nature in c++ to get quick updates (QXYSeries replace method). Lots of locking and pointer tracking and nasty stuff. You might not need such performance... and I honestly don't but I wanted many many charts moving in close to human perceptible realtime (not cpu realtime) and didn't want the QML LineSeries data update speed to ever be an issue.

    QML data updates are remarkably slower than c++ replace.

    I can help if you are interested. My way of handling speedy updates might not be "the" way, just a way that works for me. The real way I suspect is just piss of QML ChartView and do a widget chart... but I like QML and everything else lives there so I made it happen.

    But the simple axis moving I think you'll find just have:
    a timer / event updated visible time axis with an invisible lineseries (seems to need at least on record).
    invisible time axis with visible LineSeries for data which data is updated whenever your data or data axis ranges are ( I only expose a range of total data all from c++ land) so i take copies for visible series but only of data in selected range.

    Hope this makes sense.



  • Hello @6thC . Thanks a lot for your reply. Yes I can understand partly your approach. I would like you to help me on your approach.

    Meantime, I tried what you suggested. I made two axis, one fake axis with single data point in line series. But I could not scroll this axis. I could scroll the whole chart, but not the single axis only.



  • Hello @milan. Take a look at this post https://forum.qt.io/topic/93398/sliding-grid-for-chart.
    If you want to know the pseudo-algorithm check this one https://forum.qt.io/topic/88318/chartview-with-a-circular-buffer.



  • @milan I'd like to assist further but this is probably easier, I had a couple hours earlier but my work got in the way. I'm not sure when I'll get to check this.

    This should let you see the basic idea - hey gives you something to do anyhow!

    It's a waste of code if I don't send it so while not refined:

    import QtQuick 2.11
    import QtCharts 2.2
    import QtQuick.Window 2.11
    
    Window {
        id:root;
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        property real epochCreated :  new Date(Date.now()).valueOf();
        property real chartAge     : Date.now() - root.epochCreated;
    
        property real tzMs: ((new Date().getTimezoneOffset()) * 60000); // returns minuites not MS so we need to convert down
    
        property real spanMs: 120000; // 2 min in ms
    
        //function updateTimeAxis(chartTimeMin, chartTimeMax, memoryAddress){ // cpp remote control calls me
        function updateTimeAxis()// chartTimeMin, chartTimeMax){
        {
        //    root.chartAge = Date.now() - root.epochCreated; // update age
            var now = Date.now();
            dateTimeAxis.min = new Date((now - root.spanMs) + root.tzMs); //chartTimeMin);
            dateTimeAxis.max = new Date( now                + root.tzMs); //chartTimeMax);
    
       //     dateTimeAxisVisible.min = new Date(root.chartAge - dateTimeAxis.max.valueOf());
       //     dateTimeAxisVisible.max = new Date(root.chartAge - dateTimeAxis.min.valueOf());
        }
        Timer {
                  id: timer
            interval: 250
             running: true
              repeat: true
            onTriggered: {
                //var now = Date.now();
                updateTimeAxis();// now - 120000, now);
            }
        }
        ChartView {
            id: chartView
            width: root.width
            height: root.height
            antialiasing: true
            legend.visible: false
    
            ValueAxis {
                id: valueAxis
                min: 0
                max: 20
                tickCount: 10
                minorTickCount: 2
            }
    
            DateTimeAxis {// move with time
                id: dateTimeAxisVisible;
                visible: true;
                reverse: true;
                format: "mm.ss"
                min: new Date(root.chartAge - dateTimeAxis.max.valueOf()); // init
                max: new Date(root.chartAge - dateTimeAxis.min.valueOf()); // init
            }
            LineSeries {
                id: nothingSeries
                useOpenGL: true
                axisX: dateTimeAxisVisible
                axisY: valueAxis
                XYPoint { x:  new Date(Date.now()).getTime(); y: 0 }
            }
    
            DateTimeAxis {
                id: dateTimeAxis
                visible: false;
            }
            LineSeries {
                id: lineSeries
                name: "Line Series"
                axisXTop: dateTimeAxis
                axisY   : valueAxis
                XYPoint { x: (new Date(Date.now())).getTime() + root.tzMs      ; y:0;    }
                XYPoint { x: (new Date(Date.now())).getTime() + root.tzMs +1500; y:1.1;  }
                XYPoint { x: (new Date(Date.now())).getTime() + root.tzMs +2000; y:10.9; }
                XYPoint { x: (new Date(Date.now())).getTime() + root.tzMs +2500; y:2.1;  }
                XYPoint { x: (new Date(Date.now())).getTime() + root.tzMs +3100; y:20.9; }
                XYPoint { x: (new Date(Date.now())).getTime() + root.tzMs +3500; y:3.4;  }
                XYPoint { x: (new Date(Date.now())).getTime() + root.tzMs +4000; y:4.1;  }
                XYPoint { x: (new Date(Date.now())).getTime() + root.tzMs +4500; y:10;   }
                XYPoint { x: (new Date(Date.now())).getTime() + root.tzMs +5000; y:19.1; }
                XYPoint { x: (new Date(Date.now())).getTime() + root.tzMs +5500; y:11.9; }
                XYPoint { x: (new Date(Date.now())).getTime() + root.tzMs +6000; y:16.1; }
                XYPoint { x: (new Date(Date.now())).getTime() + root.tzMs +6500; y:12.9; }
                XYPoint { x: (new Date(Date.now())).getTime() + root.tzMs +7000; y:13.4; }
                XYPoint { x: (new Date(Date.now())).getTime() + root.tzMs +7500; y:14.1; }
            }
        }
    }
    
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.