Resize window but preserve aspect ratio?



  • I'm working on a program, I want the user to be able to resize the mainwindow, but I want to preserve the mainwindow's aspect ratio. if the window started as a square, it will stay square.

    the initial idea was capturing the window resize event.
    once the user resizes the window, force the width and the height to maintain the aspect ratio. However, calling resize within resizeevent will result in stack overflow.

    Another way I thought of is using a timer. The timer periodically checks window size, and re-enforces the aspect ratio if it has changed. The problem is that it's very flickering.

    Do you know any other ways?



  • Reimplement "QWidget::heightForWidth":http://doc.qt.digia.com/qt/qwidget.html#heightForWidth Return the prefered height for given width.



  • Hi!

    You can achieve it also with "horizontal layouts":https://qt-project.org/doc/qt-4.8/qhboxlayout.html and "vertical layouts":https://qt-project.org/doc/qt-4.8/qvboxlayout.html.

    If you have an .ui, just group widgets with the tool buttons over the form, and if you has just typed code, implement something like this:

    MainWindow.h:
    @
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QMainWindow>
    #include <QtGui> //I know this include here is a bad practice, but never mind, it's an example

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

    private:
    QPushButton *one;
    QPushButton *two;
    QComboBox *three;
    QComboBox *four;
    QLineEdit *five;
    QVBoxLayout *oneLayout;
    QHBoxLayout *secondLayout;
    QVBoxLayout *mainLayout;
    QWidget *centralWidget; //here could be your sub-classed widget

    };

    #endif // MAINWINDOW_H@

    MainWindow.cpp

    @#include "mainwindow.h"

    MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    {
    centralWidget = new QWidget(this);
    one = new QPushButton("Hello");
    two = new QPushButton("Goodbye");
    three = new QComboBox();
    four = new QComboBox();
    five = new QLineEdit("Now it is time");

    oneLayout = new QVBoxLayout();
    oneLayout->addWidget(one);
    oneLayout->addWidget(two);
    
    secondLayout = new QHBoxLayout();
    secondLayout->addWidget(three);
    secondLayout->addWidget(four);
    
    mainLayout = new QVBoxLayout();
    mainLayout->addWidget(five);
    mainLayout->addLayout(oneLayout);
    mainLayout->addLayout(secondLayout);
    
    centralWidget->setLayout(mainLayout);
    
    setCentralWidget(centralWidget);
    

    }

    MainWindow::~MainWindow()
    {

    }@

    And your main.cpp

    @#include <QApplication>
    #include "mainwindow.h"

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec&#40;&#41;;
    

    }@

    And a .pro if you want to copy-paste:

    @#-------------------------------------------------

    Project created by QtCreator 2012-12-20T08:50:52

    #-------------------------------------------------

    QT += core gui

    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

    TARGET = untitled
    TEMPLATE = app

    SOURCES += main.cpp
    mainwindow.cpp

    HEADERS += mainwindow.h@

    Hope this->helps();


  • Moderators



  • [quote author="QMartin" date="1355990800"]You can achieve it also with "horizontal layouts":https://qt-project.org/doc/qt-4.8/qhboxlayout.html and "vertical layouts":https://qt-project.org/doc/qt-4.8/qvboxlayout.html.[/quote]

    Hi @QMartin, I do not see how you can preserve widget aspect ratio in your example ...



  • Hello @cincirin

    It is done automatically, MainWindow resizes the centralWidget when mainWindow's size changes. So when I set a centralWidget and inside the central widget I specify one layout, these are resized preserving aspect ratio. Try it!

    Regards



  • [quote author="QMartin" date="1355991441"]Hello @cincirin

    It is done automatically, MainWindow resizes the centralWidget when mainWindow's size changes. So when I set a centralWidget and inside the central widget I specify one layout, these are resized preserving aspect ratio. Try it!

    Regards[/quote]

    I dont think that is the requirement as it is specified in the first post

    bq. I want to preserve the mainwindow’s aspect ratio. if the window started as a square, it will stay square.



  • Central widget doesn't force the width and the height to maintain the aspect ratio. For example @billconan wants widget to be always a square. So as me and @Tobias mentioned above, by simply reimplenting "QWidget::heightForWidth":http://doc.qt.digia.com/qt/qwidget.html#heightForWidth you can achieve this very easy



  • Oh...

    At first I thought everything in the window should preserve its ratio... without taking care about the initial size :S

    Sorry then...



  • Thank you guys,

    But I tried implementing heightForWidth, the function doesn't get called. I can still resize the window freely? Any ideas?

    @
    class MainWindow : public QWidget
    {
    Q_OBJECT

    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    private:

    QTimer timer;
    
    void resizeEvent(QResizeEvent *);
    void mouseReleaseEvent(QMouseEvent *);
    virtual int heightForWidth ( int w ) { return w*9/16;};
    

    private slots:
    void onTimeOut();
    };
    @

    @
    MainWindow::MainWindow(QWidget *parent) :
    QWidget(parent)
    {
    QSizePolicy qsp(QSizePolicy::Preferred,QSizePolicy::Preferred);
    qsp.setHeightForWidth(true);
    setSizePolicy(qsp);
    }
    @



  • Hi, first you forgot const modifier for heightForWidth function. Second I didn't tested on top level window which seems to be the problem, see "Trading Height for Width":http://doc.qt.digia.com/qq/qq04-height-for-width.html


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.