Any news concerning this subject ? Sorry of insisting, but I want to adopt Qwt as the plotting library in our products (and tools) and some of the issues it brings (unlike QCP) are really frustrating.
Thanks.
Any news concerning this subject ? Sorry of insisting, but I want to adopt Qwt as the plotting library in our products (and tools) and some of the issues it brings (unlike QCP) are really frustrating.
Thanks.
Last edited by embeddedmz; 20th June 2019 at 14:13.
I had a quick look at your demo and the problem is related to the implementation of QWidget::updateGeometry().Any news concerning this subject ?
When looking into the implementation you can see, that it blocks posting the LayoutRequest events, when the parent is not visible. In your situation updateGeometry is called from the scale widget and the parent is the plot widget being invisible. Not sure, why this is implemented like this in qwidget.cpp as updates are processed for QLayouts - so I'm tempted to call it a Qt bug.
A possible workaround for your demo would be:
Qt Code:
{ d_plot->d_spectrogram->setData( new SpectrogramData() ); if ( !d_plot->isVisible() ) d_plot->updateLayout(); // does not cause expensive operation, when being done before the replot d_plot->replot(); });To copy to clipboard, switch view to plain text mode
A possible workaround in qwt_scale_widget.cpp would be:
Qt Code:
{ .... if ( update_geometry ) { updateGeometry(); if ( auto w = parentWidget() ) { if ( !w->isVisible() ) } update(); } }To copy to clipboard, switch view to plain text mode
You would have a similar amount of problems when migrating the other way round. But QCP is a commercial product and you can pay for what you expect from me to do for free.Sorry of insisting, but I want to adopt Qwt as the plotting library in our products (and tools) and some of the issues it brings (unlike QCP) are really frustrating.
Uwe
embeddedmz (21st June 2019)
Hello Uwe,
First of all, thank you very much for your reply, that's very kind of you.
This workaround won't work. I have already tried it : calling updateLayout before replot won't fix the replot issue. However, I will use the condition to avoid updating the layout after the replot uselessly. I will try the second workaround another time (soon).
Qt Code:
if ( !d_plot->isVisible() ) d_plot->updateLayout(); // does not cause expensive operation, when being done before the replotTo copy to clipboard, switch view to plain text mode
Otherwise (in the same subject), I have an issue reploting the QwtPlotSpectrogram with a slider (screenshot in my second post) : I use the slider to rescale the data range and I am doing this :
Qt Code:
// dLower, dUpper are double variables (new data range) axis->setColorMap(QwtInterval(dLower, dUpper), new LinearColorMapRGB()); // I need to do this, otherwise, the color bar will change //axis->setColorBarEnabled(true); // already done elsewhere RawPlotData* spectroData = static_cast<RawPlotData*>(m_spectrogram.data()); if (spectroData) { spectroData->SetZRange(dLower, dUpper); // here I'm just calling setInterval(Qt::ZAxis, QwtInterval(dLower, dUpper) on the QwtMatrixRasterData object } m_plot->replot(); // I tried also to call repaint after it etc...To copy to clipboard, switch view to plain text mode
But the replot with or without updateLayout and/or repaint, doesn't update the shown result. Only resizing the window, replots the data with the new data range.
Last edited by embeddedmz; 21st June 2019 at 11:29.
The problem is about a missing layout update - not replotting. And on my box the workaround solved it in the demo code ( note, that updateLayout needs to be alled after setAxisScale and before replot ). So maybe you are talking about a different situation/problem now ?This workaround won't work. I have already tried it : calling updateLayout before replot won't fix the replot issue.
Your code is changing attributes behind the back of the spectrogram item and therefore its internal cache is not invalidated. It is not wrong to do things this way, but then you have to help the spectrogram item by calling:Otherwise (in the same subject), I have an issue reploting the QwtPlotSpectrogram with a slider ...
HTH,Qt Code:
m_spectrogram->invalidateCache().To copy to clipboard, switch view to plain text mode
Uwe
embeddedmz (21st June 2019)
I called updateLayout just before replot, so after any eventual setAxisScale call. I even copied/pasted your code with the workaround in the demo and nothing changed !The problem is about a missing layout update - not replotting. And on my box the workaround solved it in the demo code ( note, that updateLayout needs to be alled after setAxisScale and before replot ). So maybe you are talking about a different situation/problem now ?
My Qt version is 5.12.3 by the way and actually working under Ubuntu 18.04 (but will also run the program on Centos 7 later).
Like for the yRight axis's color bar issue (see the comment above), reassigning a new color map to the spectrogram object fixed my issue ! It's not pretty but it doesn't matter
Qt Code:
m_spectrogram.setColorMap(new LinearColorMapRGB());To copy to clipboard, switch view to plain text mode
Invalidating the cache worked perfectly ! Awesome, thank you !
Last edited by embeddedmz; 21st June 2019 at 11:53.
Ah yes I only checked the other workaround. Calling updateLayout does not work because the missing LayoutRequest is from the autoscaler for the x axis, that happens in replot.
But this one should work:
The situations is kind of specific as you need to do changes for an invisible plot, that has been shown before at least once. Sending the LayoutRequest manually is of course stupid and leads to a recalulation of the layout, that is not always necessary. But it doesn't result in recreating the image of your spectrogram, what is the heavy operation, that needs to be avoided.Qt Code:
{ d_plot->d_spectrogram->setData( new SpectrogramData() ); d_plot->replot(); });To copy to clipboard, switch view to plain text mode
The other workaround in qwt_scale_widget is a better one, as it avoids any pointless operation. I will add it as a fix to the Qwt code - something like this:
HTH,Qt Code:
if ( update_geometry ) { updateGeometry(); { if ( !w->isVisible() && w->layout() == NULL ) { if ( w->testAttribute( Qt::WA_WState_Polished ) ) } } update(); }To copy to clipboard, switch view to plain text mode
Uwe
embeddedmz (21st June 2019)
Neat !
I have two more questions (I'm really curious) :
- What does "Qt::WA_WState_Polished" mean ? is this made to handle the case when a plot has already been shown but was reploted when it's hidden ?
- As mentionned somewhere in this thread : what do you think about the fact that I need to set an expanding vertical and horizontal size policy for the QwtPlot which is a child of another QWidget so that the QwtPlot takes all the available space (like in the screenshots) and not like this : small_spectrogram.jpg
I have also a suggestion : when changing the range of data of a spectrogram, I need also to rescale the color bar of the yRight axis :
Qt Code:
axis->setColorMap(QwtInterval(dLower, dUpper), new LinearColorMapRGB());To copy to clipboard, switch view to plain text mode
The problem is that I need to make a memory allocation each time I need to rescale, whereas I only need to change the interval (first parameter). There's indeed this const method, but it returns a copy :
Qt Code:
QwtInterval colorBarInterval() const;To copy to clipboard, switch view to plain text mode
It would be great if there's a non const method that returns a reference to the internal QwtInterval, so we can modify it without reallocating a new color map !
It is an attribute, that is set once the widget has received a QEvent::Polish event - see https://doc.qt.io/qt-5/qwidget.html#ensurePolished.What does "Qt::WA_WState_Polished" mean ?
A widget always gets an initial resize event that leads in case of the plot widget to calling updateLayout and there is no reason to trigger extra updates before that. So checking for Qt::WA_WState_Polished is a minor optimization for this initial phase.
A widget doesn't take any space it is always the parent that gives its children their geometries. So obviously your parent widget does this according to the size policies of its children. The default size policy of the plot widget is QSizePolicy::MinimumExpanding in both directions - why your parent does what it does then is hard to say without knowing your code.what do you think about the fact that I need to set an expanding vertical and horizontal size policy for the QwtPlot which is a child of another QWidget so that the QwtPlot takes all the available space
Uwe
embeddedmz (23rd June 2019)
Hi all, first post in the forum. I had the same resize problem as the OP.
I wanted to show a bar plot:
Qt Code:
QwtCustomPlot(parent) { QwtColumnSymbol *columnSymbol; columnSymbol = new QwtColumnSymbol(QwtColumnSymbol::Box); columnSymbol->setLineWidth(0); columnSymbol->setFrameStyle(QwtColumnSymbol::NoFrame); _barChart = new QwtPlotBarChart(); _barChart->setLayoutPolicy(QwtPlotBarChart::AutoAdjustSamples); _barChart->setSpacing(2); _barChart->setMargin(0); _barChart->setSymbol(columnSymbol); _barChart->attach(this); }To copy to clipboard, switch view to plain text mode
inherited from the custom plotter
Qt Code:
{ plotLayout()->setCanvasMargin(0); setAttribute(Qt::WA_Hover); setAutoFillBackground(true); QwtText axisText; }To copy to clipboard, switch view to plain text mode
which sets the canvas margin to 0, hence filling the canvas with the bar plot.
Since a bar is 1 unit wide, the x axis range of n bars goes from -0.5 to n-0.5. I scale it manually at each update:
Qt Code:
void BarChart::setBars(const QVector<double> &values) { if(values.isEmpty()) return; setAxisScale( -0.5, values.size()-0.5); _barChart->setSamples(values); }To copy to clipboard, switch view to plain text mode
This works as long as I don't resize the plot, with the bar at the extremes adjacent to the widget border.
However, resizing the plot resets the canvas margins to 0.5 units to the extremes, hence changing the layout.
The solution was to force the canvas margins to follow the scale
Qt Code:
plotLayout()->setAlignCanvasToScales(true);To copy to clipboard, switch view to plain text mode
The resize now keeps the layout unaltered!
Bookmarks