Hi all.

I have implemented own class of series data, derived from QwtSeriesData, and use the method setRectOfInterest(),
for loading of data with required interval from the database:

Qt Code:
  1. class SourceSeries : public QwtSeriesData<QPointF>
  2. {
  3. ...
  4. void setRectOfInterest(const QRectF &rect)
  5. {
  6. // do something for querying of data from the database
  7. }
  8. ...
  9. }
To copy to clipboard, switch view to plain text mode 

I need to implement the behavior of plot like the "cpuplot" example,
where the X-axis displays timestamps which are updates every second.

When I need to update the data (replot the curve), I do this:

Qt Code:
  1. CURVE_UPDATE_INTERVAL_MSECS = 1000; // update every second
  2.  
  3. void Plot::timerEvent(QTimerEvent *)
  4. {
  5. m_interval = QwtInterval(m_interval.minValue() + CURVE_UPDATE_INTERVAL_MSECS,
  6. m_interval.maxValue() + CURVE_UPDATE_INTERVAL_MSECS);
  7.  
  8. setAxisScale(QwtPlot::xBottom, m_interval.minValue(), m_interval.maxValue());
  9.  
  10. replot();
  11. }
To copy to clipboard, switch view to plain text mode 

But, the problem is that the queries to the database spend some time (they are
synchronous ~200 msec), and I got the "lags" in this time. E.g. when I try to move the
plot's window on a desktop, I see some "jumps" of window.

So, I looked the Qwt sources, and now I have an idea how to avoid this, but I'm
not sure that my idea is correct.

Now, I want to start the future inside of setRectOfInterest() with the query
to the database. And when it finishes, then call the Plot::replot().

Qt Code:
  1. QFutureWatcher< QList<QPointF> > *m_watcher = new QFutureWatcher<QList<QPointF>>(this);
  2. connect(m_watcher, &QFutureWatcher::finished, this, &SourceSeries::update);
  3.  
  4. void SourceSeries::setRectOfInterest(const QRectF &rect)
  5. {
  6. const QFuture< QList<QPointF> > future = QtConcurrent::run(<function to DB query>);
  7. m_watcher->setFuture(future);
  8. }
  9.  
  10. void SourceSeries::update()
  11. {
  12. const QList<QPointF> points = m_watcher->result();
  13. m_points = points;
  14.  
  15. emit dataUpdated(); // This notified of subscribers that we can do replot
  16. }
To copy to clipboard, switch view to plain text mode 

Then the Plot's code will be modified to:

Qt Code:
  1. void Plot::timerEvent(QTimerEvent *)
  2. {
  3. m_interval = QwtInterval(m_interval.minValue() + CURVE_UPDATE_INTERVAL_MSECS,
  4. m_interval.maxValue() + CURVE_UPDATE_INTERVAL_MSECS);
  5.  
  6. setAxisScale(QwtPlot::xBottom, m_interval.minValue(), m_interval.maxValue());
  7.  
  8. updateAxes(); /// This will call the setRectOfInterest
  9. }
  10.  
  11. connect(m_series, &SourceSeries::dataUpdated, m_plot, &Plot::redraw);
  12.  
  13. void Plot::redraw()
  14. {
  15. const bool ok = QMetaObject::invokeMethod(
  16. canvas(), "replot", Qt::DirectConnection );
  17. }
To copy to clipboard, switch view to plain text mode 

The problem is in that I don't know how to notify the Plot to redraw the canvas contents, as
all Qwt's classes are not derived from the QObject. Of course, I can derive it himself,
but I'm not sure in that it is correct.

Is there are proper way do to asynchronous data loading?


BR,
Denis