Unsolved 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.
-
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; } } } }