I want to keep an aspect ratio of 16/9 on a QGroupBox (the one on the left on the screenshot below). For the tests I made a simple program with 4 groupboxes in a vertical layout, all in an horizontal layout:

#include "MainWindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
MainWindow.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
qDebug() << "horizontalLayout->hasHeightForWidth: " << ui->horizontalLayout->hasHeightForWidth();
}
MainWindow::~MainWindow()
{
delete ui;
}
MainWindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1000</width>
<height>703</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="GroupBoxHFW" name="groupBox_1">
<property name="title">
<string>GroupBox</string>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="minimumSize">
<size>
<width>485</width>
<height>204</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>485</width>
<height>204</height>
</size>
</property>
<property name="title">
<string>GroupBox</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="minimumSize">
<size>
<width>485</width>
<height>204</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>485</width>
<height>204</height>
</size>
</property>
<property name="title">
<string>GroupBox</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="minimumSize">
<size>
<width>485</width>
<height>204</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>485</width>
<height>204</height>
</size>
</property>
<property name="title">
<string>GroupBox</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1000</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>GroupBoxHFW</class>
<extends>QGroupBox</extends>
<header>GroupBoxHFW.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
GroupBoxHFW.h
#ifndef GROUPBOXHFW_H
#define GROUPBOXHFW_H
#include <QGroupBox>
class GroupBoxHFW : public QGroupBox
{
public:
GroupBoxHFW(QWidget * parent = 0);
GroupBoxHFW(const QString & title, QWidget * parent = 0);
int heightForWidth(int w) const;
bool hasHeightForWidth() const;
};
#endif // GROUPBOXHFW_H
GroupBoxHFW.cpp
#include "GroupBoxHFW.h"
#include <QDebug>
GroupBoxHFW::GroupBoxHFW(QWidget * parent) : QGroupBox(parent)
{
QSizePolicy policy(this->sizePolicy());
policy.setHeightForWidth(true);
this->setSizePolicy(policy);
}
GroupBoxHFW::GroupBoxHFW(const QString & title, QWidget * parent) : QGroupBox(title, parent)
{
QSizePolicy policy(this->sizePolicy());
policy.setHeightForWidth(true);
this->setSizePolicy(policy);
}
int GroupBoxHFW::heightForWidth(int w) const
{
qDebug() << "GroupBoxHFW::heightForWidth called";
return 9.f / 16.f * w;
}
bool GroupBoxHFW::hasHeightForWidth() const
{
qDebug() << "GroupBoxHFW::hasHeightForWidth called";
return true;
}
As you can see, I reimplemented the virtual functions int heightForWidth(int w) const
and bool hasHeightForWidth() const
, hoping my QGroupBox would resize automatically to a 16/9 aspect ratio. Unfortunately, it doesn't work. GroupBoxHFW::heightForWidth()
is called only once when the program starts and it doesn't even resize the widget.
Here is the output of the program:
GroupBoxHFW::hasHeightForWidth called
horizontalLayout->hasHeightForWidth: true
GroupBoxHFW::hasHeightForWidth called
GroupBoxHFW::heightForWidth called
GroupBoxHFW::hasHeightForWidth called
GroupBoxHFW::hasHeightForWidth called
GroupBoxHFW::hasHeightForWidth called
GroupBoxHFW::hasHeightForWidth called
What's even weirder is that none of the functions above (hasHeightForWidth()
and heightForWidth()
get called when I resize the window, while the QGroupBox is resized.
What's wrong?
Your approach could work if this group box was inside vertical layout.
As name says hasHeightForWidth
is well defined when height depends on width (this was designed for text wrapping), not another way around (your case).
What you can do? Try this (I've implemented something similar for QGraphicsWidget
and it was working quite well):
QSize GroupBoxHFW::sizeHint() const {
QSize s = size();
lastHeight = s.height();
s.setWidth((s.height()*16)/9);
s.setHeight(QGroupBox::sizeHint().height());
return s;
}
void GroupBoxHFW::resizeEvent(QResizeEvent * event) {
QGroupBox::resizeEvent(event);
if (lastHeight!=height()) {
updateGeometry(); // it is possible that this call should be scheduled to next iteration of event loop
}
}
Small off topic:
If I would do that I would try implement this functionality by subclass a QLayout
and not as a subclass of some QWidget
. This way this it could be used multiple times for different widgets.
来源:https://stackoverflow.com/questions/24264320/qt-layouts-keep-widget-aspect-ratio-while-resizing