Plotting chart using lots of data
-
Hi, I am plotting chart using
qchart
andqlineseries
requiring lots of values, and the processing of values takes long time which blocks the GUI. To optimize this issue, I am trying to move the processing procedure into another thread. And I would like to ask 2 questions:-
I am now appending values into
qlineseries
like:for(int i = 0; i < dataCount; i++) { series->append(val[i]); }
I realized it's very time consuming, since I am appending one by one, I noticed there's
QVXYModelMapper
which can append the whole data model once, may I ask is it faster to useQVXYModelMapper
? I think maybe I can also tryappend(const QList<QPointF> &points);
which loads all values just once.-
I am facing the thread affinity problem.
First I created QChartView in GUI(main) thread:
QChartView *chartView = new QChartView;
Then I construct the
worker
class for appending data to line series, I moveworker
to another thread, loading data intoqlineseries
inworker::loadData
First I do:
Worker *worker = new worker(chartView);
worker ->moveToThread(thread);
Then in loadData:
void Worker::loadData() { QLineSeries *series = new QLineSeries; // loading data into series, time-consuming //..... chartView->append(series); // chartView is constructed in main thread // Error: QObject::setParent: Cannot set parent, new parent is in a different thread }
looks like I cannot change
chartView
which is constructed in main thread, is there a way to resolve this? I heard people use signal and slot https://stackoverflow.com/questions/3268073/qobject-cannot-create-children-for-a-parent-that-is-in-a-different-threadThank you very much
-
-
@StudyQt1
I don't know about the first question. For the second one, in Qt only the main UI thread should access any UI stuff. So your computation thread cannot do thechartView->append(series)
(and I don't think you should pass it tonew worker(chartView);
). The idea is that at the end the time-consuming series population the thread should emit signal passing the series to be plotted and the main UI thread should have a slot to receive it and do thechartView->append(series)
in the main UI thread. -
@StudyQt1 said in Plotting chart using lots of data:
@JonB I think "UI stuff" means classes inherited from QWidget ?
It's a bit more than just
QWidget
, hence my "UI stuff" terminology :) For example,QImage
can be accessed in a secondary thread, butQPixmap
cannot;QGraphics...
objects are notQWidget
s but can't be accessed by another thread. But yes, for your purposes, certainly all widgets. -
@StudyQt1 said in Plotting chart using lots of data:
chartView->append(series);
I don't understand this.
I think it will take more time if the lineseries are attached on the chart while you are loading the data. It would be an idea if you could give an example number for the lot of data and time you are talking about.
-
@JonB Thank you very much for your help, I put "GUI staff" back to GUI thread and the problem is resolved.
May I ask another question: Long-time processing functions may cause GUI frozen & not responding, in this case we need to put them into new threads. But how to determine which functions are "long" freezing the GUI, which are "short"? Is there a generic way to decide?
Now I just run those functions to "see" & "feel" which block the GUI from responding, this is too random -
@StudyQt1 said in Plotting chart using lots of data:
Is there a generic way to decide?
Use a profiler. If you're using GCC you can use https://www.thegeekstuff.com/2012/08/gprof-tutorial/
Easier way which is often enough is simply to put debug output at the beginning and end of your methods/functions with timestamps and then check the output of your application while it is running.