0

I'm building an application that plots measurement data using the QtCharts library. Some important things that should be mentioned are:

  1. I am dealing with time series.

  2. The measurement data is obtained offline, which means it has already been obtained. My program just reads it from the file and displays it.

  3. I am working with a for-loop that takes the data points as chunks of a fixed size (say 10000) and adds them to the scatter series. This way, the data is being "replayed" and the user can see the progression of the measurement data at many intermediate time points and not just after all data points have been plotted.

  4. I am working with a whole lot of data points, on the order of millions.

At every iteration of the loop a new QScatterSeries is created, data points are appended, the scatter series is added to the chart and then the chart view is repainted. In the beginning it is quite fast, but as time progresses the number of points to be painted increases and the painting process becomes slower and slower. I know for a fact that I can reimplement the paintEvent of the chart view class to get it to redraw only part of itself. I think I can make it faster by updating only the parts that have new data points. I will just calculate the coordinates of the region where new data points were added and use the paintEvent. But how do I do it? I tried using the setClipRect() method of QPainter, but couldn't do it. Thanks in advance.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Onat Tanriover
  • 131
  • 1
  • 1
  • 4

1 Answers1

0

QGraphicsView/QGraphicsItem don't implement it.

They don't because it's unfortunately generally impossible: the displayed items (e.g. series) are scaled and antialiased. In the old days when everything was displayed in device units, and was drawn directly on the window, doing partial updates made sense: you'd first use a fast blit to shift the existing plot, and then draw new points.

Alas, in any non-trivial scene viewer, the relationship between the horizontal device (widget) units and the item (chart/series) units is not 1:1, so there's no general way to scroll the data in device units and have it still make sense in chart units.

There are is a workaround: Scroll by some larger-than-needed (rounded up) number of device units, then back-calculate what scroll it yields in chart units, and then offset the chart by such a number (i.e. move the X axis range accordingly).

This could be implemented with relative ease in the sources of the QGraphicsView system, as the chart builds on it. There's no way to "bolt this on" externally - you need to add such support directly to QGraphicsView and QGraphicsItem infrastructure, and then have the QChartView leverage it. If you're not in the habit of building your own Qt, you can of course copy the necessary classes over to your codebase and rename them.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • First of all, thanks for the reply. There may be some things that I couldn't make very clear. First of all, since all the data points are available at the beginning, I will first find the min and max of these points for both coordinates and then set the ranges of the axes to these values. This way, there will be no need of rescaling the axes. In addition, there will be no need of redrawing the points that were already on the chart, because their positions will not change. The new data points will be placed on regions that were previously blank. So I just wanna give the location of this region – Onat Tanriover Sep 02 '17 at 13:05