Qml F1 Legends

This application demonstrates how to use XmlListModel as a datasource for a Chart.

Running the Example

To run the example from Qt Creator, open the Welcome mode and select the example from Examples. For more information, visit Building and Running an Example.

Using List Models as Data Sources

Let's define an empty ChartView first:


  ChartView {
      id: chartView
      title: "Driver Speeds, lap 1"
      anchors.fill: parent
      legend.alignment: Qt.AlignTop
      animationOptions: ChartView.SeriesAnimations
      antialiasing: true
  }

Our XmlListModel uses hard-coded test data. In a real application the data source would be a timing system.


  XmlListModel {
      // Hard-coded test data
      xml: "<results><row><speedTrap>0</speedTrap><driver>Fittipaldi</driver><speed>104.12</speed></row>"
          +"<row><speedTrap>0</speedTrap><driver>Stewart</driver><speed>106.12</speed></row>"
          +"<row><speedTrap>0</speedTrap><driver>Hunt</driver><speed>106.12</speed></row>"
      ...
      query: "/results/row"

      XmlRole { name: "speedTrap"; query: "speedTrap/string()" }
      XmlRole { name: "driver"; query: "driver/string()" }
      XmlRole { name: "speed"; query: "speed/string()" }
  }
  // An example XmlListModel containing F1 legend drivers' speeds at speed traps
  SpeedsXml {
      id: speedsXml
      onStatusChanged: {
          if (status == XmlListModel.Ready) {
              timer.start();
          }
      }
  }

The data is parsed with a timer. The line series representing each driver are created on the fly.


  // A timer to mimic refreshing the data dynamically
  Timer {
      id: timer
      interval: 700
      repeat: true
      triggeredOnStart: true
      running: false
      onTriggered: {
          currentIndex++;
          if (currentIndex < speedsXml.count) {
              // Check if there is a series for the data already
              // (we are using driver name to identify series)
              var lineSeries = chartView.series(speedsXml.get(currentIndex).driver);
              if (!lineSeries) {
                  lineSeries = chartView.createSeries(ChartView.SeriesTypeLine,
                                                      speedsXml.get(currentIndex).driver);
                  chartView.axisY().min = 0;
                  chartView.axisY().max = 250;
                  chartView.axisY().tickCount = 6;
                  chartView.axisY().titleText = "speed (kph)";
                  chartView.axisX().titleText = "speed trap";
                  chartView.axisX().labelFormat = "%.0f";
              }
              lineSeries.append(speedsXml.get(currentIndex).speedTrap,
                                speedsXml.get(currentIndex).speed);

              if (speedsXml.get(currentIndex).speedTrap > 3) {
                  chartView.axisX().max = Number(speedsXml.get(currentIndex).speedTrap) + 1;
                  chartView.axisX().min = chartView.axisX().max - 5;
              } else {
                  chartView.axisX().max = 5;
                  chartView.axisX().min = 0;
              }
              chartView.axisX().tickCount = chartView.axisX().max - chartView.axisX().min + 1;
          } else {
              // No more data, change x-axis range to show all the data
              timer.stop();
              chartView.animationOptions = ChartView.AllAnimations;
              chartView.axisX().min = 0;
              chartView.axisX().max = speedsXml.get(currentIndex - 1).speedTrap;
          }
      }
  }

Files: