5
votes

I understand that in Qt4, there is no single flag you can set to have the mouse driven resizing of the window maintain a certain aspect ratio (say, 1:1). Is there a way to force a new size for the window while in "resizeEvent (QResizeEvent * event)"? the parameters of the event don't seem to support change or give the user a chance to inject a new size.

My goal: GUI/Mouse resizing of a certain window will maintain its current aspect ratio, regardless of where you resize it from (sides, top, bottom, corners).

3

3 Answers

3
votes

Quoting a message in the thread referenced by @blueskin:

This is surprisingly difficult to do. Most of the window systems do not allow the application to set constraints on the window other than the max and min sizes and that it can be fixed size.

The most common way to attempt this is to call resize from within the resize event. This often causes recursion problems or looks strange because the widget resizes in ways the user has not requested.

Since most window systems do not allow the main window to be resized appropriately, the best solution is often to constrain a child widget rather than the parent. One such way to do this is with a class provided by libqxt.

libqxt has support for keeping a child widget at a certain aspect ratio through its QxtLetterBoxWidget. @blueskin's answer provides one good attempt at doing what was originally requested.

If you're interested I'd recommend you read the source for the resizeWidget() function and observe the places in which it gets called. As background, libqxt uses the pimpl idiom and qxt_d() gets at the private member.

2
votes

Duplicate Question? How to maintain widgets aspect ratio in Qt?

Citing the answer by 'df' in the above link

Calling resize() from within resizeEvent() has never worked well for me -- at best it will cause flickering as the window is resized twice (as you have), at worst an infinite loop.

I think the "correct" way to maintain a fixed aspect ratio is to create a custom layout. You'll have to override just two methods, QLayoutItem::hasHeightForWidth() and QLayoutItem::heightForWidth().

Also checkout Sam Dutton's solution @ http://lists.trolltech.com/qt-interest/2007-01/msg00204.html

void MyWindow::resizeEvent(QResizeEvent * /*resizeEvent*/) 
{
    int containerWidth = _myContainerWidget->width();
    int containerHeight = _myContainerWidget->height();

    int contentsHeight = containerHeight ;
    int contentsWidth = containerHeight * _aspectRatio;
    if (contentsWidth > containerWidth ) {
        contentsWidth = containerWidth ;
        contentsHeight = containerWidth / _aspectRatio;
    }

    resizeContents(contentsWidth, contentsHeight);
}
2
votes

Another quick and simpler way to do it: http://developer.qt.nokia.com/forums/viewthread/5320/#31866

#include <QWidget>
#include <QApplication>
#include <QSizePolicy>

class MyWidget:public QWidget
{
public:
  MyWidget():QWidget(){};
  ~MyWidget(){};
  virtual int heightForWidth ( int w ) const { return w*9/16;};
};

int main (int argv, char** argc)
{
  QApplication a(argv,argc);
  MyWidget w;
  QSizePolicy qsp(QSizePolicy::Preferred,QSizePolicy::Preferred);
  qsp.setHeightForWidth(true);
  w.setSizePolicy(qsp);
  w.show();

  a.exec();
}