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. Sliding Grid for Chart

Sliding Grid for Chart

Scheduled Pinned Locked Moved Solved QML and Qt Quick
5 Posts 2 Posters 3.7k 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.
  • Z Offline
    Z Offline
    zansara
    wrote on last edited by zansara
    #1

    Hello everyone,

    I am trying to implement a sliding-grid plot in QML. So far I managed to make my LineSeries slide, but I have no idea on how to move the underlying grid. I have checked the docs for ChartView, LIneSeries and ValueAxis, with no luck. Did I miss something?

    I have seen people suggesting to use a CategoryAxis to control the position of ticks, but to me it does not look like an optimal solution, as I would need to implement the sliding logic myself.

    I have also checked out QCustomPlot already. It offers exactly what I need, but it is not suitable for my requirements, because I have to use exclusively QML ( at most some JS ) to draw the charts.

    Here is a minimal example of what I mean. As you can see, the grid is fixed, while the tick values update as the line series slides.

    import QtQuick 2.9
    import QtQuick.Layouts 1.0
    import QtCharts 2.1
    
    Item {
        id: root
        width: 640
        height: 480
    
        property int numpoints: 628;
        property double step: 0.01;
    
        Timer { 
            id: timer; 
            interval: 1;
            repeat: true;
            onTriggered: {
                draw( xAxis, yAxis, lineSeries, lineSeries.at(0).y );
            }
        }
    
        function draw(xax, yax, lineSeries, dataPoint){
            lineSeries.remove(0);
            xax.min = xax.min + step;
            xax.max = xax.max + step;
    
            var x = lineSeries.at(lineSeries.count-1).x + step ;
            lineSeries.append( x, dataPoint );
            if(dataPoint > yax.max){
                yax.max = dataPoint +1;
            } else if(dataPoint < yax.min){
                yax.min = dataPoint -1;
            }
        }
    
    
        ColumnLayout {
            anchors.rightMargin: 20
            anchors.leftMargin: 20
            anchors.bottomMargin: 20
            anchors.topMargin: 20
            anchors.fill: parent
    
            ChartView {
                id: chartView
                width: 631
                height: 400
                Layout.fillHeight: true
                Layout.fillWidth: true
                title: "Sliding Grid"
                antialiasing: true
                legend {
                    alignment: Qt.AlignBottom
                }
    
                ValueAxis {
                    id: xAxis
                    min: 0
                    max: numpoints * step + (numpoints*step)/6;
    
                    tickCount: 5
                    minorTickCount: 5
                }
    
                ValueAxis {
                    id: yAxis
                    min: 0
                    max: 10
    
                    tickCount: 5
                    minorTickCount: 5
                }
    
                LineSeries {
                    id: lineSeries
                    name: "Line Series"
                    axisX: xAxis
                    axisY: yAxis
                }
            }
    
            Component.onCompleted: {
                for (var i = 0; i < numpoints; i++) {
                    lineSeries.append(i*step, Math.sin(i*step) * 3 + 5);
                }
                timer.start()
            }
        }
    }
    

    Do you have any suggestion? If you know any other good plotting libraries for QML, feel free to suggest them.

    DiracsbracketD 1 Reply Last reply
    0
    • Z zansara

      Hello everyone,

      I am trying to implement a sliding-grid plot in QML. So far I managed to make my LineSeries slide, but I have no idea on how to move the underlying grid. I have checked the docs for ChartView, LIneSeries and ValueAxis, with no luck. Did I miss something?

      I have seen people suggesting to use a CategoryAxis to control the position of ticks, but to me it does not look like an optimal solution, as I would need to implement the sliding logic myself.

      I have also checked out QCustomPlot already. It offers exactly what I need, but it is not suitable for my requirements, because I have to use exclusively QML ( at most some JS ) to draw the charts.

      Here is a minimal example of what I mean. As you can see, the grid is fixed, while the tick values update as the line series slides.

      import QtQuick 2.9
      import QtQuick.Layouts 1.0
      import QtCharts 2.1
      
      Item {
          id: root
          width: 640
          height: 480
      
          property int numpoints: 628;
          property double step: 0.01;
      
          Timer { 
              id: timer; 
              interval: 1;
              repeat: true;
              onTriggered: {
                  draw( xAxis, yAxis, lineSeries, lineSeries.at(0).y );
              }
          }
      
          function draw(xax, yax, lineSeries, dataPoint){
              lineSeries.remove(0);
              xax.min = xax.min + step;
              xax.max = xax.max + step;
      
              var x = lineSeries.at(lineSeries.count-1).x + step ;
              lineSeries.append( x, dataPoint );
              if(dataPoint > yax.max){
                  yax.max = dataPoint +1;
              } else if(dataPoint < yax.min){
                  yax.min = dataPoint -1;
              }
          }
      
      
          ColumnLayout {
              anchors.rightMargin: 20
              anchors.leftMargin: 20
              anchors.bottomMargin: 20
              anchors.topMargin: 20
              anchors.fill: parent
      
              ChartView {
                  id: chartView
                  width: 631
                  height: 400
                  Layout.fillHeight: true
                  Layout.fillWidth: true
                  title: "Sliding Grid"
                  antialiasing: true
                  legend {
                      alignment: Qt.AlignBottom
                  }
      
                  ValueAxis {
                      id: xAxis
                      min: 0
                      max: numpoints * step + (numpoints*step)/6;
      
                      tickCount: 5
                      minorTickCount: 5
                  }
      
                  ValueAxis {
                      id: yAxis
                      min: 0
                      max: 10
      
                      tickCount: 5
                      minorTickCount: 5
                  }
      
                  LineSeries {
                      id: lineSeries
                      name: "Line Series"
                      axisX: xAxis
                      axisY: yAxis
                  }
              }
      
              Component.onCompleted: {
                  for (var i = 0; i < numpoints; i++) {
                      lineSeries.append(i*step, Math.sin(i*step) * 3 + 5);
                  }
                  timer.start()
              }
          }
      }
      

      Do you have any suggestion? If you know any other good plotting libraries for QML, feel free to suggest them.

      DiracsbracketD Offline
      DiracsbracketD Offline
      Diracsbracket
      wrote on last edited by Diracsbracket
      #2

      @zansara said in Sliding Grid for Chart:

      it does not look like an optimal solution, as I would need to implement the sliding logic myself.

      The suggested approach using CategoryAxis works, and is actually quite simple to implement, if you give it a try: it requires minimal implementation logic, of which you already did most of the work.

      There is no other solution, I'm afraid.

      0_1533551579411_movinggrid.gif

      (GIF animation is frame-reduced because max. 1MB allowed, it seems)

      1 Reply Last reply
      0
      • Z Offline
        Z Offline
        zansara
        wrote on last edited by
        #3

        Thank you for your feedback.

        I got it working using CategoryAxis, as you said. Am I wrong, or there is no way to draw the minor ticks? I see no mention to them in the docs.

        This is what I have now:

        import QtQuick 2.9
        import QtQuick.Layouts 1.0
        import QtCharts 2.1
        
        Item {
            id: root
            width: 640
            height: 480
        
            property int numpoints: 628;
            property double step: 0.01;
        
            Timer { 
                id: timer; 
                interval: 1;
                repeat: true;
                onTriggered: {
                    draw( xAxis, yAxis, lineSeries, lineSeries.at(0).y );
                    if( xAxis.max - xAxis.categoriesLabels[xAxis.categoriesLabels.length -1] > 1 ){
                        xAxis.append(xAxis.max.toFixed(0), xAxis.max);
                        xAxis.remove(xAxis.categoriesLabels[0]);
                    }
                }
            }
        
            function draw(xax, yax, lineSeries, dataPoint){
                lineSeries.remove(0);
                xax.min = xax.min + step;
                xax.max = xax.max + step;
        
                var x = lineSeries.at(lineSeries.count-1).x + step ;
                lineSeries.append( x, dataPoint );
                if(dataPoint > yax.max){
                    yax.max = dataPoint +1;
                } else if(dataPoint < yax.min){
                    yax.min = dataPoint -1;
                }
            }
        
        
            ColumnLayout {
                anchors.rightMargin: 20
                anchors.leftMargin: 20
                anchors.bottomMargin: 20
                anchors.topMargin: 20
                anchors.fill: parent
        
                ChartView {
                    id: chartView
                    width: 631
                    height: 400
                    Layout.fillHeight: true
                    Layout.fillWidth: true
                    title: "Sliding Grid"
                    antialiasing: true
                    legend {
                        alignment: Qt.AlignBottom
                    }
        
                    CategoryAxis {
                        id: xAxis
                        min: 0
                        max: numpoints * step + (numpoints*step)/6;
        
                        labelsPosition: CategoryAxis.AxisLabelsPositionOnValue;
                        Component.onCompleted: {
                            for(var i=0; i<max+1; i++){
                                xAxis.append( i, i );
                            }
                        }
                    }
        
                    ValueAxis {
                        id: yAxis
                        min: 0
                        max: 10
        
                        tickCount: 5
                        minorTickCount: 5
                    }
        
                    LineSeries {
                        id: lineSeries
                        name: "Line Series"
                        axisX: xAxis
                        axisY: yAxis
        
                        Component.onCompleted: {
                            for (var i = 0; i < numpoints; i++) {
                                lineSeries.append(i*step, Math.sin(i*step) * 3 + 5);
                            }
                            timer.start();
                        }
                    }
                }
            }
        }
        

        The only issue I see with this approach is relative to performance, but I am still investigating how fast I can push the updates and how many FPS I can achieve. If you have any suggestion from this point of view, that would be great.

        DiracsbracketD 1 Reply Last reply
        0
        • Z zansara

          Thank you for your feedback.

          I got it working using CategoryAxis, as you said. Am I wrong, or there is no way to draw the minor ticks? I see no mention to them in the docs.

          This is what I have now:

          import QtQuick 2.9
          import QtQuick.Layouts 1.0
          import QtCharts 2.1
          
          Item {
              id: root
              width: 640
              height: 480
          
              property int numpoints: 628;
              property double step: 0.01;
          
              Timer { 
                  id: timer; 
                  interval: 1;
                  repeat: true;
                  onTriggered: {
                      draw( xAxis, yAxis, lineSeries, lineSeries.at(0).y );
                      if( xAxis.max - xAxis.categoriesLabels[xAxis.categoriesLabels.length -1] > 1 ){
                          xAxis.append(xAxis.max.toFixed(0), xAxis.max);
                          xAxis.remove(xAxis.categoriesLabels[0]);
                      }
                  }
              }
          
              function draw(xax, yax, lineSeries, dataPoint){
                  lineSeries.remove(0);
                  xax.min = xax.min + step;
                  xax.max = xax.max + step;
          
                  var x = lineSeries.at(lineSeries.count-1).x + step ;
                  lineSeries.append( x, dataPoint );
                  if(dataPoint > yax.max){
                      yax.max = dataPoint +1;
                  } else if(dataPoint < yax.min){
                      yax.min = dataPoint -1;
                  }
              }
          
          
              ColumnLayout {
                  anchors.rightMargin: 20
                  anchors.leftMargin: 20
                  anchors.bottomMargin: 20
                  anchors.topMargin: 20
                  anchors.fill: parent
          
                  ChartView {
                      id: chartView
                      width: 631
                      height: 400
                      Layout.fillHeight: true
                      Layout.fillWidth: true
                      title: "Sliding Grid"
                      antialiasing: true
                      legend {
                          alignment: Qt.AlignBottom
                      }
          
                      CategoryAxis {
                          id: xAxis
                          min: 0
                          max: numpoints * step + (numpoints*step)/6;
          
                          labelsPosition: CategoryAxis.AxisLabelsPositionOnValue;
                          Component.onCompleted: {
                              for(var i=0; i<max+1; i++){
                                  xAxis.append( i, i );
                              }
                          }
                      }
          
                      ValueAxis {
                          id: yAxis
                          min: 0
                          max: 10
          
                          tickCount: 5
                          minorTickCount: 5
                      }
          
                      LineSeries {
                          id: lineSeries
                          name: "Line Series"
                          axisX: xAxis
                          axisY: yAxis
          
                          Component.onCompleted: {
                              for (var i = 0; i < numpoints; i++) {
                                  lineSeries.append(i*step, Math.sin(i*step) * 3 + 5);
                              }
                              timer.start();
                          }
                      }
                  }
              }
          }
          

          The only issue I see with this approach is relative to performance, but I am still investigating how fast I can push the updates and how many FPS I can achieve. If you have any suggestion from this point of view, that would be great.

          DiracsbracketD Offline
          DiracsbracketD Offline
          Diracsbracket
          wrote on last edited by
          #4

          @zansara said in Sliding Grid for Chart:

          Am I wrong, or there is no way to draw the minor ticks?

          I'm afraid that it looks that way :-(

          I did basically the same as you to obtain the above animation:

              property int numpoints: 126
          
              property int numTicks: 10
              property double step: 10
              property double range: numpoints*step
              property double tickStep:range/numTicks
          
              property int tickCounter: 0
          
              Timer {
                  id: timer
                  interval: 100
                  repeat: true
                  onTriggered: {
                      draw( xAxis, yAxis, lineSeries, lineSeries.at(0).y );
                  }
              }
          
              function draw(xax, yax, lineSeries, dataPoint){
                  lineSeries.remove(0);
          
                  xax.min = xax.min + step;
                  xax.max = xax.max + step;
          
                  var x = lineSeries.at(lineSeries.count-1).x + step ;
                  lineSeries.append( x, dataPoint );
          
                  if(dataPoint > yax.max){
                      yax.max = dataPoint +1;
                  } else if(dataPoint < yax.min){
                      yax.min = dataPoint -1;
                  }
          
                  if (xax.min > parseFloat(xax.categoriesLabels[1])) {
                      updateGrid(xax.categoriesLabels[0])
                  }
              }
          
              function updateGrid(minVal){
                  ++tickCounter
                  xAxis.remove(minVal)
                  var newTick = (tickCounter + numTicks-1)*tickStep
                  xAxis.append(newTick.toString(), newTick)
              }
          
               function initGrid(minVal){
                  for (var j=0; j<numTicks; ++j){
                      var endValue = minVal + j*tickStep
                      xAxis.append(endValue.toString(), endValue)
                  }
          
                  xAxis.min = minVal
                  xAxis.max =  minVal + (numTicks-1)*tickStep
          
                  tickCounter = 0
              }
          
              ColumnLayout {
                  anchors.rightMargin: 20
                  anchors.leftMargin: 20
                  anchors.bottomMargin: 20
                  anchors.topMargin: 20
                  anchors.fill: parent
          
                  ChartView {
                      id: chartView
                      width: 631
                      height: 400
                      Layout.fillHeight: true
                      Layout.fillWidth: true
                      title: "Sliding Grid"
                      antialiasing: true
                      legend {
                          alignment: Qt.AlignBottom
                      }
          
                      CategoryAxis {
                          id: xAxis
                          labelsPosition: CategoryAxis.AxisLabelsPositionOnValue
                      }
          
                      ValueAxis {
                          id: yAxis
                          min: 0
                          max: 10
          
                          tickCount: 5
                          minorTickCount: 5
                      }
          
                      LineSeries {
                          id: lineSeries
                          name: "Line Series"
                          axisX: xAxis
                          axisY: yAxis
                      }
                  }
          
                  Component.onCompleted: {
                      for (var i = 0; i < numpoints; i++) {
                          lineSeries.append(i*step, Math.sin(i*step/100) * 3 + 5);
                      }
          
                      initGrid(0)
                      timer.start()
                  }
              }
          
          1 Reply Last reply
          0
          • Z Offline
            Z Offline
            zansara
            wrote on last edited by
            #5

            @Diracsbracket said in Sliding Grid for Chart:

            @zansara said in Sliding Grid for Chart:

            Am I wrong, or there is no way to draw the minor ticks?

            I'm afraid that it looks that way :-(

            I see... However, many thanks for your time! :)

            1 Reply Last reply
            0

            • Login

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