The main window of my Qt/C++ program looks like this:
As you can see on the picture, the window consists essentially of:
- a menu on the left
- two "canvases"
What I want is straightforward to describe: I want that under resizing of the window, both canvases take as much space as possible, but still remain squares (width = height). I've been trying to achieve that unsuccessfully.
Let me quickly describe the objects:
- The window is a class
Window
that I created deriving QWidget. It has aQGridLayout
for a layout. - The window's layout has three widgets: the left menu
LeftMenu *menu
, and the canvasesCanvas *leftCanvas, *rightCanvas
. BothLeftMenu
andCanvas
are custom classes deriving QWidget.
(NB: the left menu actually consists of 3 different widgets (submenus), and the window also has a status bar and a top menu, but I don't think it matters for my question.)
I have been "playing" (not having fun the least bit) with QSizePolicy's etc to try to get the Canvases' sizes to behave like I want (be as large as possible inside the window, but keep height/width ratio = 1), unsuccessfully. Let me describe my latest attempt in case that is useful for you (if you already know a solution to my problem, you don't have to keep reading):
I overrode the methods heightForWidth()
, sizeHint()
and minimumSizeHint()
for Canvas like so:
class Canvas : public QWidget
{
Q_OBJECT
friend class Window;
public:
explicit Canvas(Window* window);
...
private:
void resizeEvent(QResizeEvent *resizeEvent) override;
int heightForWidth(int width) const override {return width;}
QSize sizeHint() const override
{
int size = std::min(width(), height());
return QSize(size, size);
}
QSize minimumSizeHint() const override {return QSize(200,200);}
...
};
And the constructor of my class Window looks like (a bit simplified):
Window::Window(ActionHandler *handler)
{
leftMenu = new LeftMenu(this);
leftMenu->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
leftCanvas = new Canvas(this);
rightCanvas = new Canvas(this);
QSizePolicy policy(QSizePolicy::Expanding, QSizePolicy::Maximum);
policy.setHeightForWidth(true);
leftCanvas->setSizePolicy(policy);
rightCanvas->setSizePolicy(policy);
layout = new QGridLayout;
layout->setColumnMinimumWidth(0, menuWidth());
layout->addWidget(leftMenu, 0, 0);
layout->addWidget(leftCanvas, 0, 1);
layout->addWidget(rightCanvas, 0, 2);
setLayout(layout);
}
My idea was that as long as the width of the canvases is the limiting factor, the sizePolicy
of the canvases should be (QSizePolicy::Expanding, QSizePolicy::Maximum)
. And as soon as the height of the canvases becomes the limiting factor, I would change the sizePolicy of the canvases (probably in Canvas::resizeEvent()
) to the opposite: (QSizePolicy::Maximum, QSizePolicy::Expanding)
. Does that sound too complicated?
Anyway, it already fails, and I don't understand why. If I shrink the window horizontally it gives me this:
So, the height of the canvases does not shrink. I do not understand this behavior. In the Qt documentation (http://doc.qt.io/qt-4.8/qsizepolicy.html#Policy-enum), I read:
QSizePolicy::Maximum The sizeHint() is a maximum. The widget can be shrunk any amount without detriment if other widgets need the space (e.g. a separator line). It cannot be larger than the size provided by sizeHint().
The behavior of my canvases here seems to contradict this: their height is larger than the height provided by their sizeHint(). (I did make sure by std::couting "live": the canvas sizeHint, its height, its sizePolicy and its hasHeightForWidth parameters).