QCustomPlot Discussion and Comments

Plotting In Other Threads, It Is Safe?Return to overview

It is safe to call QCustomPlot::replot() with QCustomPlot::rpRefreshHint in another thread? I know that is not a good idea to manipulate QWidget from other threads, But my problem was plotting 6k(1k per graph) points in 5 instance of QCustomPlot(points are added using QCPGraph::addData() and I got performance issues with QCustomPlot::replot().

So I tried to move QCustomPlot::replot to another thread and it just work fine without any issue and the performance problem was fixed.

Sample Code:

#include "qcustomplot.h"

#include <QApplication>
#include <QPointer>
#include <QVector>
#include <QThread>
#include <QTimer>
#include <QTime>

class QCustomPlotUpdater : public QObject {
 public:
  QCustomPlotUpdater(QVector<QPointer<QCustomPlot>> const& plots)
      : plots_(plots),
        thread_(new QThread),
        start_time_(QTime::currentTime()) {
    connect(thread_, &QThread::finished, this, &QObject::deleteLater);
    connect(thread_, &QThread::started, &updater_, qOverload<>(&QTimer::start));
    connect(&updater_, &QTimer::timeout, this, &QCustomPlotUpdater::addNewPoint);
    updater_.setInterval(std::chrono::milliseconds(16));
  }
  void start() {
    thread_->start();
  }

 private:
  void addNewPoint() {
    double const key = start_time_.msecsTo(QTime::currentTime()) / 1000.0;
    for (auto const& plot : plots_) {
      for (int index = 0, end = plot->graphCount(); index < end; ++index) {
        plot->graph(index)->addData(
            key * ((index + 1) * 0.25),
            qSin(key) + std::rand() / (double)RAND_MAX * 1 * qSin(key / 0.3843));
      }
      plot->rescaleAxes();
      plot->replot(QCustomPlot::rpRefreshHint);
    }
  }

  QVector<QPointer<QCustomPlot>> plots_;
  QPointer<QThread> thread_;
  QTime const start_time_;
  QTimer updater_;
};

auto CreateCustomPlot() {
  QPointer<QCustomPlot> result = new QCustomPlot;
  for (int i = 0; i < 4; ++i) result->addGraph();
  result->setMinimumSize(500, 300);
  return result;
}

int main(int argc, char* argv[]) {
  QApplication app(argc, argv);
  QVector plots = {
      CreateCustomPlot(),
      CreateCustomPlot(),
      CreateCustomPlot(),
      CreateCustomPlot(),
  };
  auto* const updater = new QCustomPlotUpdater(plots);
  updater->start();
  for (auto const& plot : plots) plot->show();
  app.exec();
}

You could find the complete project files here: https://gist.github.com/another-ghasem/5052517283d14968339c4177b86181f0

I also tried compiling with: -fsanitize=undefined,thread and it's report nothing.

- Compiler: Debian clang version 11.0.1-2~deb10u1
- OS: Debian Buster 4.19.235-1
- Qt: 5.15.2
- QCustomPlot: 2.1.0, released on March 29, 2021

+ moveToThread() Added.