QwtPlotRescaler extra space
Good afternoon,
I am trying to keep the aspect ratio of my spectrogram when I resize the window, that is, there are circular shapes inside my graph and I'm trying to keep their shape as I change the window, as long as maintaining the top y and bottom x interval limits ( in this case yLeft and xBottom both should go from -1.5 to 1.5).
As suggested in a different thread, I used the QwtPlotRescaler library to maintain the aspect ratio between the lower x axis and left y axis, but it unfortunately only solved half of my problem (literally) because I was able to maintain the shape at the cost of modifying the x axis ( because i yLeft is my reference axis) so that it does not go from -1.5 to 1.5 (I also decided to set QwtPlotRescaler::ExpandBoth in order not to make it look so bad). Is there any way to solve this problem?
My piece of code for the rescaler is:http://doc.qt.io/qt-4.8/
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QwtPlotRescaler *rescaler = new QwtPlotRescaler(ui->myPlot->canvas(), QwtPlot::yLeft, QwtPlotRescaler::Fixed);
rescaler->setExpandingDirection(QwtPlotRescaler::ExpandBoth );
rescaler->setAspectRatio(QwtPlot::xBottom,1.0);
rescaler->setAspectRatio(QwtPlot::yRight,0.0)
}
Thank you,
Jorge
Re: QwtPlotRescaler extra space
Quote:
Originally Posted by
airflow
there are circular shapes inside my graph and I'm trying to keep their shape as I change the window, as long as maintaining the top y and bottom x interval limits ( in this case yLeft and xBottom both should go from -1.5 to 1.5).
When the physical plot canvas is not square and you need to have fixed axes ranges you have to accept, that the mapping between plot and widget coordinates is different. But what about your circles - are how are width and height of then related to plot coordinates ?
Uwe
Re: QwtPlotRescaler extra space
Thank you for your answer Uwe,
I understand that for any resize event where [-1.5, 1.5] are to remain fixed proportions should change. But the way that would make sense for me would be if the canvas would change only as possible according to the mainwindow, that is, the canvas would change only with vertical stretching, for example. But I have no idea how to implement this...
Also, the circles are mapped to plot coordinates in the standard fashion, which come with spectrogram definitions (this is a spectrogram plot btw)
Thanks
Re: QwtPlotRescaler extra space
The overall problem for implementing your behavior is the way how the layout engine ( QwtPlotLayoutEngine ) of the plot is implemented.
It subtracts all spaces needed for title, footer, legend and axes first and then the canvas - as it is the only element, that is adjustable - gets the rest. But for your use case you have to start with the canvas arranging all other elements around it. Unfortunately such an engine doesn't exist.
So what you can do is to anticipate the size needed for those other parts by using their size hints. Then you could add these sizes to the size of the canvas you want to have and manually resize the plot widget.
( Of course you don't need to use QwtPlotRescaler then anymore ).
You could also try to overload from QwtPlotLayout::activate() and implement your strategy there. Reading the code of this class is no fun, but as you know your plot you can ignore corner cases and might find a much simpler way.
HTH,
Uwe
Re: QwtPlotRescaler extra space
Hello,
Your solution is working like a charm, I can finally get the behaviour I want, with the right rescaling factor, except when I first start the application where the plot doesn't open with the right scale (probably because resizeEvent is not emitted when the app is first opened so it opens with the QtDesigner initial size for the widget), so I tried to find a way of manually calling the resizeEvent right after I open my app but without much success. Is there any way to force the program to first call my resizeEvent user-defined function, or should I open the app maximized(which is the solution I've found so far...))
Hope this wasn't too confusing...
Best regards,
Jorge
Re: QwtPlotRescaler extra space
Quote:
Originally Posted by
airflow
Is there any way to force the program to first call my resizeEvent user-defined function, or should I open the app maximized(which is the solution I've found so far...))
Well, someone needs to call resize, that it happens, I don't know about your application, but I usually this is the job of the parent ( often done by its layout ) of your plot.
But note that updating the layout of the plot has to be done in more situations. So better move your code into some doLayout() method that can also be used, when receiving QEvent::LayoutRequest events.
Or even better: try overload QwtPlot::updateLayout and put your code there. If this is possible you don't need to take care of when to call what.
You could also check QEvent::PolishRequest if you need to do an initial operation.
Uwe
1 Attachment(s)
Re: QwtPlotRescaler extra space
Quote:
Originally Posted by
Uwe
Or even better: try overload QwtPlot::updateLayout and put your code there. If this is possible you don't need to take care of when to call what.
Uwe
I have been trying to do this by creating a class that inherits from QwtPlot and by overriding the virtual function updateLayout. I think everythink would work fine if there would be a way of making the plot fill the whole widget! I mean, before having this derived class (plotclass.h), I would go to the QtDesigner, right click over the selected widget and choose the option "Promote to" and then "QwtPlot" and everything would be okay since the plot would fill the entire widget space.
The code for my derived class is:
Code:
#include "plotclass.h"
#include "qwt_scale_widget.h"
plotClass
::plotClass(QWidget *parent
):{
;
}
void plotClass::updateLayout()
{
int width_yRight;
int height_xBottom;
int width_yLeft;
if(this
->axisEnabled
(QwtPlot::yRight)) width_yRight
= this
->axisWidget
(QwtPlot::yRight)->width
();
else
width_yRight = 0;
if(this
->axisEnabled
(QwtPlot::yLeft) && this
->axisEnabled
(QwtPlot::xBottom)) {
height_xBottom
= this
->axisWidget
(QwtPlot::xBottom)->height
();
width_yLeft
= this
->axisWidget
(QwtPlot::yLeft)->width
();
}
else
{
height_xBottom = 0;
width_yLeft = 0;
}
int h = this->height();
int w = (h-height_xBottom) + (width_yLeft+width_yRight);
this->resize(w,h);
this->move((this->parentWidget()->width()-w)/2,(this->parentWidget()->height()-h)/2);
}
and the code for the main window which creates an instance of it is:
Code:
(...)
ui->setupUi(this);
myPlot = new plotClass(ui->widget);
(...)
, in which widget is the widget I created on the qt designer to be the container of plotclass.
Attachment 12755
This is basically what I am getting, isn't it possible to tell the qwtplot to fill the whole parent widget?
Thank you!
Re: QwtPlotRescaler extra space
Quote:
Originally Posted by
airflow
This is basically what I am getting, isn't it possible to tell the qwtplot to fill the whole parent widget?
It always works the other way round: the parent ( often using a layout ) is responsible for the geometry of its children.
So add a layout for the parent or overload its resizeEvent and call plot->setGeometry manually.
Uwe
1 Attachment(s)
Re: QwtPlotRescaler extra space
That solved half of my problem, thank you! Now when I first open the app, the dimensions are correct but the xBottom axis doesn't have the right Interval, and so the image is "cut" at the very beginning, and if I try to resize the window, everything is just perfect. Is it an initial setup configuration problem in my updatelayout function? How can I Setup my plot so that it starts with the right data interval? I have tried to set an axis manually but it doesn't seem to work!
Thanks
Attachment 12756
The interval should be [-1.5, 1.5]
Re: QwtPlotRescaler extra space
Well QwtPlot::updateLayout() is about adjusting the content to a given geometry, not about changing the geometry. So the posted implementation will never work !
Better try something like this:
Code:
{
public:
virtual void activate
( const QwtPlot *plot,
const QRectF &rect, Options options
) {
const QRectF rect
= adjustedRect
( plot, rect
);
}
};
and
Code:
plot->setPlotLayout( new YourPlotLayout() );
Then it boils down to finding an implementation for YourPlotLayout::adjustedRect(). Here you have to start with finding a square rectangle for the canvas, that has to be expanded, by the space needed for the axes, title, footer, legend.
Of course you could also try to find a complete new implementation for YourPlotLayout::activate(). In this case you would also start with the square canvas, but then you would also calculate all the other geometries yourself.
Uwe