Results 1 to 16 of 16

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

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    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 14:13.

  2. #2
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,312
    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

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

    embeddedmz (21st June 2019)

  4. #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,

    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 11:29.

  5. #4
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,312
    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

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

    embeddedmz (21st June 2019)

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

    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 11:53.

  8. #6
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,312
    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

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

    embeddedmz (21st June 2019)

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

    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 !

  11. #8
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,312
    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

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

    embeddedmz (23rd June 2019)

  13. #9
    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, 21:23
  2. Replies: 0
    Last Post: 8th June 2012, 13:27
  3. Replies: 0
    Last Post: 7th June 2012, 21:58
  4. Widget does not resize correctly
    By Demandred in forum Newbie
    Replies: 4
    Last Post: 16th April 2010, 12:06
  5. Program that just shows a window
    By claudio-cit in forum Newbie
    Replies: 2
    Last Post: 5th July 2008, 09: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.