Height for Width - Maintaining Aspect Ratio of a QWidget
-
Hi everyone, I'm new here, hope this is in the right section.
Looking for some expert help. I've been googling all afternoon. It seems like there used to be a solution for this question, but the links are dead.
I want to have a widget within a set of nested layouts maintain a square aspect ratio. I've created a simple "main.cpp" to illustrate my problem.
The following code is my best stab at getting QWidget "theWidget" to stay square, but it doesn't:
#include <QApplication> #include <QPushButton> #include <QApplication> #include <QLayout> #include <QSizePolicy> #include <QLabel> int main(int argc, char **argv) { QApplication app (argc, argv); //Create Primary Widget QWidget *window = new QWidget; window->setMinimumSize(100, 100); // Create Secondary Widget that SHOULD be Square QLabel *theWidget = new QLabel("Hello World!", window); QSizePolicy thePolicy = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); QHBoxLayout *theLayout = new QHBoxLayout; // Format Secondary Widget theWidget->setFrameStyle(QFrame::Panel | QFrame::Raised); theWidget->setLineWidth(2); theWidget->setAlignment(Qt::AlignCenter | Qt::AlignCenter); theWidget->setMinimumSize(100, 100); // Attempt to Square Secondary Widget thePolicy.setHeightForWidth(true); theWidget->setSizePolicy(thePolicy); // Add Secondary Widget to a Layout theLayout->addWidget(theWidget); // Set the Primary Widget to have the Layout. window->setLayout(theLayout); window->show(); return app.exec(); }
-
Hi, sadly, the
setHeightForWidth
property only works in aQGraphicsLayout
that got changed a while ago.Since that change, I don't know of an inbuild way to force a square Aspect Ratio of a widget in a
normal
QLayout, accept rewriting theResizeEvent
protected: virtual void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; ... void resizeEvent(QResizeEvent *event) { event->accept(); if(event->size().width() > event->size().height()){ QWidget::resize(event->size().height(),event->size().height()); }else{ QWidget::resize(event->size().width(),event->size().width()); } }
Maybe someone else has a better solution.
-
@J.Hilk Thanks very much. This did the trick! Not sure what sort of pitfalls are in store for reimplementing resizeEvent, but I haven't found any yet!
I will post back here if I find a problem. :)
My Adjustment to Your Solution:
mycustomwidget.h:
#ifndef MYCUSTOMWIDGET_H #define MYCUSTOMWIDGET_H #include <QWidget> #include <QResizeEvent> class MyCustomWidget : public QWidget { Q_OBJECT public: explicit MyCustomWIdget(QWidget *parent=0); protected: virtual void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; }; #endif // MYCUSTOMWIDGET_H
mycustomwidget.cpp:
MyCustomWidget::MyCustomWidget(QWidget *parent) : QWidget(parent) { // Implementation doesn't pertain to this example... } void MyCustomWidget::resizeEvent(QResizeEvent *event) { event->accept(); if(event->size().width() > event->size().height()){ QWidget::resize(event->size().height(),event->size().height()); }else{ QWidget::resize(event->size().width(),event->size().width()); } }
Thanks again!
-
@Drakkhan I should mention, that this
resize
inResizeEvent
can easily end in an recursive loop.
This should be pretty safe, if it is a standalone window for example. But if you have to be careful, if you want to use it in QLayout. Those tend to be difficult.I would suggest either, subclassing and making your own
QLayout
Flow Layout Example or nesting your custom Widget inside an other one that is effected by the Layout, and handels the positioning of your custom -square- widget.I prefer the 2nd option myself.