seanj (22nd December 2020)
Currently, my first plot paints onto a widget still, but I plan on modifying my code to paint onto a QImage in a separate thread later on. Before I do that though, I am just curious, how could I use the signal and slot mechanism to notify when I am finished painting? Would I need to re-implement paintEvent and emit a signal after calling painter.end() ?
Thank you, I greatly appreciate your help.
Added after 4 minutes:
Awesome! Thanks for the reply. I will check it out soon.
How does this compare with QwtPlotCurve::FilterPoints? When I set QwtPlotCurve::FilterPoints to true, my frame rate drops from 16.5 FPS to 14.5 FPS.
Last edited by seanj; 22nd December 2020 at 19:24.
You're probably not going to have an actual paintEvent() in your thread, but instead you will have some other method that creates a new QImage with the current data. For whatever class it is that implements this updating, be sure it is derived from QObject (so it can emit signals), and implement a signal with a signature something like:how could I use the signal and slot mechanism to notify when I am finished painting?
Qt Code:
signals: To copy to clipboard, switch view to plain text mode
In the GUI thread, add a slot to whatever QWidget class will display the image, and connect that slot to the thread's signal:
Qt Code:
public slots:To copy to clipboard, switch view to plain text mode
In that slot, copy the image, then call QWidget::update() to schedule a paintEvent().
I am not familiar enough with the current state of Qwt to know how you would integrate this QImage-based rendering into a QwtPlot. Perhaps you would need to actually paint the entire QwtPlot into the QImage in your thread, or perhaps Qwt has a spectrogram-like plot where a QImage can be substituted for a calculated spectrogram.
<=== The Great Pumpkin says ===>
Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.
seanj (23rd December 2020)
Is it possible to implement similar functionality using the slot and signal mechanism if I am painting onto a widget, not a QImage? I attempted to do so, but when I run the program, no data is ever displayed on the plot.
In plot constructor:
Qt Code:
connect(this, SIGNAL(plotUpdated()), this, SLOT(onPlotUpdated())); d_timer->singleShot(10000, this, SLOT(onTimerFinished()));To copy to clipboard, switch view to plain text mode
onTimerFinished() slot, (added single shot timer and created this because I read that signals should be emitted inside an event):
Qt Code:
void Plot::onTimerFinished() { replot(); Q_EMIT plotUpdated(); }To copy to clipboard, switch view to plain text mode
onPlotUpdated() slot:
Qt Code:
void Plot::onPlotUpdated() { if (index < 10) { // update d_curve's data d_curve->updateSamples(index); replot(); index += 1; frame += 1; // if index is 10, set to 0 to continue plotting if (index == 10) index = 0; // stop the plotting if (frame > 1000) { // set index to 11 to stop plotting index = 11; } } Q_EMIT plotUpdated(); }To copy to clipboard, switch view to plain text mode
Don't know where you read this, but it is wrong. Signals can be emitted from any method. How they get handled depends on what type of signal/slot connection was made. See the documentation for QObject::connect().I read that signals should be emitted inside an event
You realize you have set up an infinite loop here, right? You have connected the plotUpdated() signal to the onPlotUpdated() slot, and in that slot you emit the plotUpdated() signal, which calls the slot, which emits the signal, which calls the slot...onPlotUpdated() slot:
I don't have any idea what you are trying to do with this QTimer. And if all you want to do is call the onPlotUpdated slot, then make that the slot connected to the timer's timeout signal. No need to add a special slot that simply emits the plotUpdated signal.d_timer->singleShot(10000, this, SLOT(onTimerFinished()));
<=== The Great Pumpkin says ===>
Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.
seanj (28th December 2020)
1. I do not remember exactly, but I thought I read it in a Qt forum, I cannot find it anymore.
2. I am aware of the infinite loop, my plan was to just add a counter variable and only emit the signal when the count is below a certain value.
3. The sole reason I used a single shot timer is just so I could enter the event loop to emit a signal, but I now know that is not necessary.
Thank you very much for the guidance, I really appreciate it.
A small correction - the method has to be a member of a class derived from QObject that contains the Q_OBJECT macro in its class definition, and the signal function itself must be declared as a signal in that class. Otherwise the MOC compiler won't generate the boilerplate code that defines the signal and integrates it into signal / slot connections. Typically signals are private or protected class methods that can't be called except from within their own classes.Signals can be emitted from any method.
<=== The Great Pumpkin says ===>
Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.
FilterPointsAggressive limits the maximum number of lines to be painted to: 4 * canvas.width() ( or height - depending on the orientation ).
So if you have a line plot where the samples are ordered in x or y direction the effect will be very significant for 1e6 samples.
If you have a scatter plot you could try what is done in the scatterplot example.
HTH,
Uwe
seanj (23rd December 2020)
Bookmarks