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:
class SourceSeries : public QwtSeriesData<QPointF>
{
...
void setRectOfInterest
(const QRectF &rect
) {
// do something for querying of data from the database
}
...
}
class SourceSeries : public QwtSeriesData<QPointF>
{
...
void setRectOfInterest(const QRectF &rect)
{
// do something for querying of data from the database
}
...
}
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:
CURVE_UPDATE_INTERVAL_MSECS = 1000; // update every second
{
m_interval = QwtInterval(m_interval.minValue() + CURVE_UPDATE_INTERVAL_MSECS,
m_interval.maxValue() + CURVE_UPDATE_INTERVAL_MSECS);
setAxisScale
(QwtPlot::xBottom, m_interval.
minValue(), m_interval.
maxValue());
replot();
}
CURVE_UPDATE_INTERVAL_MSECS = 1000; // update every second
void Plot::timerEvent(QTimerEvent *)
{
m_interval = QwtInterval(m_interval.minValue() + CURVE_UPDATE_INTERVAL_MSECS,
m_interval.maxValue() + CURVE_UPDATE_INTERVAL_MSECS);
setAxisScale(QwtPlot::xBottom, m_interval.minValue(), m_interval.maxValue());
replot();
}
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().
QFutureWatcher< QList<QPointF> > *m_watcher = new QFutureWatcher<QList<QPointF>>(this);
connect(m_watcher, &QFutureWatcher::finished, this, &SourceSeries::update);
void SourceSeries
::setRectOfInterest(const QRectF &rect
) {
const QFuture< QList<QPointF> > future = QtConcurrent::run(<function to DB query>);
m_watcher->setFuture(future);
}
void SourceSeries::update()
{
const QList<QPointF> points = m_watcher->result();
m_points = points;
emit dataUpdated(); // This notified of subscribers that we can do replot
}
QFutureWatcher< QList<QPointF> > *m_watcher = new QFutureWatcher<QList<QPointF>>(this);
connect(m_watcher, &QFutureWatcher::finished, this, &SourceSeries::update);
void SourceSeries::setRectOfInterest(const QRectF &rect)
{
const QFuture< QList<QPointF> > future = QtConcurrent::run(<function to DB query>);
m_watcher->setFuture(future);
}
void SourceSeries::update()
{
const QList<QPointF> points = m_watcher->result();
m_points = points;
emit dataUpdated(); // This notified of subscribers that we can do replot
}
To copy to clipboard, switch view to plain text mode
Then the Plot's code will be modified to:
{
m_interval = QwtInterval(m_interval.minValue() + CURVE_UPDATE_INTERVAL_MSECS,
m_interval.maxValue() + CURVE_UPDATE_INTERVAL_MSECS);
setAxisScale
(QwtPlot::xBottom, m_interval.
minValue(), m_interval.
maxValue());
updateAxes(); /// This will call the setRectOfInterest
}
connect(m_series, &SourceSeries::dataUpdated, m_plot, &Plot::redraw);
void Plot::redraw()
{
canvas(), "replot", Qt::DirectConnection );
}
void Plot::timerEvent(QTimerEvent *)
{
m_interval = QwtInterval(m_interval.minValue() + CURVE_UPDATE_INTERVAL_MSECS,
m_interval.maxValue() + CURVE_UPDATE_INTERVAL_MSECS);
setAxisScale(QwtPlot::xBottom, m_interval.minValue(), m_interval.maxValue());
updateAxes(); /// This will call the setRectOfInterest
}
connect(m_series, &SourceSeries::dataUpdated, m_plot, &Plot::redraw);
void Plot::redraw()
{
const bool ok = QMetaObject::invokeMethod(
canvas(), "replot", Qt::DirectConnection );
}
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
Bookmarks