Results 1 to 16 of 16

Thread: Need to resize the window to make QwtPlotSpectrogram shows correctly

  1. #1
    Join Date
    Jun 2019
    Location
    France, Pau
    Posts
    60
    Thanks
    32
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Need to resize the window to make QwtPlotSpectrogram shows correctly

    Hello,

    I'm showing Qwt plots in different tabs of a QTabWidget :

    1.jpg

    The first tab is "Main" and contains two Qwt plots (curve & spectrogram, in a vertical layout with an exapanding horitzontal and vertical size policy otherwise the plots will not take all the available place - strange strange...).

    Then, I go to another tab "Baseline" to load data from a file and replot all the tabs's plots.

    My problem : the QwtSpectrogram of the main tab is not showing correctly, the yLeft axis title disappeared and the yRight axis are overflowing :

    2.jpg

    If I resize the window the plot will be repainted correctly :

    3.png

    How can I fix this ? I called repaint() after replot() but it doesn't fix the problem. It seems that the problem is that the replot is not well done if the plot belongs to a masked tab.

    Thanks !

  2. #2
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,309
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Need to resize the window to make QwtPlotSpectrogram shows correctly

    The geometry of a child is always the responsibility of the parent - the child is indicating that something relevant has changed by sending a QEvent::LayoutRequest.

    From the screenshot I guess, that you are changing something behind the back of the intended Qwt API and the necessary QEvent::LayoutRequest is not sent to the plot widget.
    If you know which operation is responsible you can try to manually call QwtPlot::updateLayout - or post a QEvent::LayoutRequest event to the plot widget, if you need an asynchronous update.

    Uwe

  3. #3
    Join Date
    Jun 2019
    Location
    France, Pau
    Posts
    60
    Thanks
    32
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Need to resize the window to make QwtPlotSpectrogram shows correctly

    Hello Uwe,

    I really didn't understand your explanation : the size of the spectrogram plot didn't change between the moment where I loaded the data and got back to the main plot (I didn't resize the window).

    Let me give you another example, I noticed that if I don't show the empty plot that is in "Spectrum" before loading the data, it will be displayed correctly. But If I show the "Spectrum" tab then load the data then go back to it the plot will not be shown correctly :

    Loading data then showing the "spectrum" tab (OK !)

    4.jpg

    Showing the "spectrum" tab, loading the datan getting back to "spectrum tab" (NOT OK)

    This 5.jpg , loading data from "Baseline" tab then going back to "Spectrum", 6.jpg

    In fact, I'm changing my plotting API to Qwt. I didn't have this problem with QCP or VTK for example ! and as I mentionned before, I was obliged to apply an exapanding horizontal and vertical size policy for the Qwt widgets otherwise they are too small.

    If I place directly in the tab widget, Qwt widgets in its layout, I can't resize the window no more (the maximize button disappears !!??!!!). That's why I'm obliged to put a Qwt widgets inside a QWidget. That's really weired (and of course I didn't have these bizarre issues with Qcp or VTK 2D plots).

    UPDATE: looking back at the last screenshots, it appears that the axis labels are not scaling correctly or something like that.
    Last edited by embeddedmz; 17th June 2019 at 14:50.

  4. #4
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,309
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Need to resize the window to make QwtPlotSpectrogram shows correctly

    Quote Originally Posted by embeddedmz View Post
    I really didn't understand your explanation : ...
    As I don't have much information about your code I can only guess from the screenshots - and those look like the internal layout inside plot widget needs to be recalculated with QwtPlot::updateLayout.

    Just to verify if I'm right you can set up a timer calling manually QwtPlot::updateLayout to see if this does the job.
    If yes the next step is to find out, why updateLayout is not called.

    The other reason I can imagine is, that the plot widget itself is not resized by its parent, what would be a bug in your layout code. You can overload QwtPlot::resizeEvent to see what size it gets and if this is the correct one. If this is your problem it might be related to your tab widget, that for some reason blocks layout calculations, when being on a different tab.

    But if you can simplify your problem to a small compilable demo I can tell you what is going wrong.

    Uwe

  5. #5
    Join Date
    Jun 2019
    Location
    France, Pau
    Posts
    60
    Thanks
    32
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Need to resize the window to make QwtPlotSpectrogram shows correctly

    Just to verify if I'm right you can set up a timer calling manually QwtPlot::updateLayout to see if this does the job.
    If yes the next step is to find out, why updateLayout is not called.
    Calling updateLayout after replot (or with a timer) fixed the problem ! Does this mean updateLayout performs a second replot after the first one ?

    I will try to produce a demo...

    Thanks.

  6. #6
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,309
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Need to resize the window to make QwtPlotSpectrogram shows correctly

    Quote Originally Posted by embeddedmz View Post
    Does this mean updateLayout performs a second replot after the first one ?
    When updateLayout leads to a different size for the plot canvas, then the content of the canvas has to be recreated from scratch. This is not exactly the same as what replot ( no update of the scale ticks/intervals ) does, but as the heavy operation ( recalculation of the spectrogram image ) is done twice you should definitely understand and fix the problem.

    Uwe

  7. #7
    Join Date
    Jun 2019
    Location
    France, Pau
    Posts
    60
    Thanks
    32
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Need to resize the window to make QwtPlotSpectrogram shows correctly

    Uwe,

    I made a quick example here https://github.com/embeddedmz/qwt_sp..._issue_example

    To reproduce the issue, show the "Plot" tab, then go back to the "Button" tab and click on its content (it's a button !), then go back to the "Plot" tab. You will see, for example, that the labels of the right y axis are overflowing.

    If you press on the button without passing by the "Plot" tab, there will be no problem !

    Maybe the problem is I'm setting an axis scale before rendering it ?

    d_plot->d_spectrogram->setData( new SpectrogramData() );
    d_plot->setAxisScale( QwtPlot::yRight, 100000, 900000 ); // <==== ????
    d_plot->replot();
    You can also check that without fixing a size policy, the plots are small !

    Regards.

  8. #8
    Join Date
    Jun 2019
    Location
    France, Pau
    Posts
    60
    Thanks
    32
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Need to resize the window to make QwtPlotSpectrogram shows correctly

    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 15:13.

  9. #9
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,309
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Need to resize the window to make QwtPlotSpectrogram shows correctly

    Any news concerning this subject ?
    I had a quick look at your demo and the problem is related to the implementation of QWidget::updateGeometry().

    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:
    1. QObject::connect(pushButton, &QPushButton::pressed, [this]()
    2. {
    3. d_plot->d_spectrogram->setData( new SpectrogramData() );
    4. d_plot->setAxisScale( QwtPlot::yRight, 100000, 900000 );
    5.  
    6. if ( !d_plot->isVisible() )
    7. d_plot->updateLayout(); // does not cause expensive operation, when being done before the replot
    8.  
    9. d_plot->replot();
    10. });
    To copy to clipboard, switch view to plain text mode 

    A possible workaround in qwt_scale_widget.cpp would be:
    Qt Code:
    1. void QwtScaleWidget::layoutScale( bool update_geometry )
    2. {
    3. ....
    4.  
    5. if ( update_geometry )
    6. {
    7. updateGeometry();
    8. if ( auto w = parentWidget() )
    9. {
    10. if ( !w->isVisible() )
    11. QApplication::postEvent( w, new QEvent(QEvent::LayoutRequest ) );
    12. }
    13. update();
    14. }
    15. }
    To copy to clipboard, switch view to plain text mode 

    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.
    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.

    Uwe

  10. The following user says thank you to Uwe for this useful post:

    embeddedmz (21st June 2019)

  11. #10
    Join Date
    Jun 2019
    Location
    France, Pau
    Posts
    60
    Thanks
    32
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Need to resize the window to make QwtPlotSpectrogram shows correctly

    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:
    1. if ( !d_plot->isVisible() )
    2. d_plot->updateLayout(); // does not cause expensive operation, when being done before the replot
    To 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:
    1. // dLower, dUpper are double variables (new data range)
    2. m_plot->setAxisScale(QwtPlot::yRight, dLower, dUpper);
    3.  
    4. QwtScaleWidget* axis = m_plot->axisWidget( QwtPlot::yRight );
    5. axis->setColorMap(QwtInterval(dLower, dUpper), new LinearColorMapRGB()); // I need to do this, otherwise, the color bar will change
    6. //axis->setColorBarEnabled(true); // already done elsewhere
    7.  
    8. RawPlotData* spectroData = static_cast<RawPlotData*>(m_spectrogram.data());
    9. if (spectroData)
    10. {
    11. spectroData->SetZRange(dLower, dUpper); // here I'm just calling setInterval(Qt::ZAxis, QwtInterval(dLower, dUpper) on the QwtMatrixRasterData object
    12. }
    13.  
    14. 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 12:29.

  12. #11
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,309
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Need to resize the window to make QwtPlotSpectrogram shows correctly

    This workaround won't work. I have already tried it : calling updateLayout before replot won't fix the replot issue.
    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 ?

    Otherwise (in the same subject), I have an issue reploting the QwtPlotSpectrogram with a slider ...
    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:

    Qt Code:
    1. m_spectrogram->invalidateCache().
    To copy to clipboard, switch view to plain text mode 
    HTH,
    Uwe

  13. The following user says thank you to Uwe for this useful post:

    embeddedmz (21st June 2019)

  14. #12
    Join Date
    Jun 2019
    Location
    France, Pau
    Posts
    60
    Thanks
    32
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Need to resize the window to make QwtPlotSpectrogram shows correctly

    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 ?
    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 !

    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:
    1. 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 12:53.

  15. #13
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,309
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Need to resize the window to make QwtPlotSpectrogram shows correctly

    Quote Originally Posted by embeddedmz View Post
    I even copied/pasted your code with the workaround in the demo and nothing changed !!
    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:

    Qt Code:
    1. QObject::connect(pushButton, &QPushButton::pressed, [this]()
    2. {
    3. d_plot->d_spectrogram->setData( new SpectrogramData() );
    4. d_plot->setAxisScale( QwtPlot::yRight, 100000, 900000 );
    5. QApplication::postEvent( d_plot, new QEvent(QEvent::LayoutRequest ) );
    6. d_plot->replot();
    7. });
    To copy to clipboard, switch view to plain text mode 
    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.

    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:

    Qt Code:
    1. if ( update_geometry )
    2. {
    3. updateGeometry();
    4.  
    5. if ( QWidget* w = parentWidget() )
    6. {
    7. if ( !w->isVisible() && w->layout() == NULL )
    8. {
    9. if ( w->testAttribute( Qt::WA_WState_Polished ) )
    10. QApplication::postEvent( w, new QEvent( QEvent::LayoutRequest ) );
    11. }
    12. }
    13.  
    14. update();
    15. }
    To copy to clipboard, switch view to plain text mode 
    HTH,
    Uwe

  16. The following user says thank you to Uwe for this useful post:

    embeddedmz (21st June 2019)

  17. #14
    Join Date
    Jun 2019
    Location
    France, Pau
    Posts
    60
    Thanks
    32
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Need to resize the window to make QwtPlotSpectrogram shows correctly

    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:
    1. 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:
    1. 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 !

  18. #15
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,309
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Need to resize the window to make QwtPlotSpectrogram shows correctly

    What does "Qt::WA_WState_Polished" mean ?
    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.

    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.

    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
    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.

    Uwe

  19. The following user says thank you to Uwe for this useful post:

    embeddedmz (23rd June 2019)

  20. #16
    Join Date
    Jan 2020
    Posts
    3
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Need to resize the window to make QwtPlotSpectrogram shows correctly

    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:
    1. BarChart::BarChart(QWidget *parent) :
    2. QwtCustomPlot(parent)
    3. {
    4. QwtColumnSymbol *columnSymbol;
    5.  
    6. columnSymbol = new QwtColumnSymbol(QwtColumnSymbol::Box);
    7. columnSymbol->setLineWidth(0);
    8. columnSymbol->setFrameStyle(QwtColumnSymbol::NoFrame);
    9. columnSymbol->setPalette(QPalette("Red"));
    10.  
    11. _barChart = new QwtPlotBarChart();
    12. _barChart->setLayoutPolicy(QwtPlotBarChart::AutoAdjustSamples);
    13. _barChart->setSpacing(2);
    14. _barChart->setMargin(0);
    15. _barChart->setSymbol(columnSymbol);
    16. _barChart->attach(this);
    17.  
    18. setAxisAutoScale(QwtPlot::yLeft);
    19. }
    To copy to clipboard, switch view to plain text mode 

    inherited from the custom plotter

    Qt Code:
    1. QwtCustomPlot::QwtCustomPlot(QWidget *parent) :
    2. QwtPlot(parent)
    3. {
    4. ((QFrame *)canvas())->setLineWidth(0);
    5. ((QFrame *)canvas())->setFrameStyle(QFrame::NoFrame);
    6. ((QFrame *)canvas())->setPalette(QColor("White"));
    7.  
    8. plotLayout()->setCanvasMargin(0);
    9.  
    10. setAttribute(Qt::WA_Hover);
    11.  
    12. setAutoFillBackground(true);
    13. enableAxis(QwtPlot::xBottom, false);
    14. enableAxis(QwtPlot::yLeft, false);
    15.  
    16. QwtText axisText;
    17. axisText.setFont(QApplication::font());
    18.  
    19. setAxisTitle(QwtPlot::xBottom, axisText);
    20. setAxisTitle(QwtPlot::yLeft, axisText);
    21. setAxisFont(QwtPlot::xBottom, QApplication::font());
    22. setAxisFont(QwtPlot::yLeft, QApplication::font());
    23. }
    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:
    1. void BarChart::setBars(const QVector<double> &values)
    2. {
    3. if(values.isEmpty())
    4. return;
    5.  
    6. setAxisScale(
    7. QwtPlot::xBottom,
    8. -0.5,
    9. values.size()-0.5);
    10.  
    11. _barChart->setSamples(values);
    12. }
    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:
    1. plotLayout()->setAlignCanvasToScales(true);
    To copy to clipboard, switch view to plain text mode 

    The resize now keeps the layout unaltered!

Similar Threads

  1. How to make a user not resize a window.
    By marcos.miranda in forum Newbie
    Replies: 2
    Last Post: 20th September 2017, 22:23
  2. Replies: 0
    Last Post: 8th June 2012, 14:27
  3. Replies: 0
    Last Post: 7th June 2012, 22:58
  4. Widget does not resize correctly
    By Demandred in forum Newbie
    Replies: 4
    Last Post: 16th April 2010, 13:06
  5. Program that just shows a window
    By claudio-cit in forum Newbie
    Replies: 2
    Last Post: 5th July 2008, 10:55

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.