resize QMainWindow based on a child widget? - c++

The child-parent hierarchy is the following: mainWindow -> centralWidget -> frame -> widget.
Widget is being resized during the application lifetime, however it is always set to a fixed size. I want the QMainWindow to resize based on that - to have a minimum size that is needed to display all the widgets.
To do that I currently have to do this.
widget->setFixedSize(x, y);
frame->setFixedSize(frame->sizeHint());
centralWidget->setFixedSize(centralWidget->sizeHint());
mainWindow->setFixedSize(mainWindow->sizeHint());
It doesn't work properly if I only resize the main window. All parents of widget need to be resized in order for this to work. Is there a more elegant way? Is it possible to make the main window call resize on all of it's children?
NOTE: All widgets except 'widget' have automatic layout management. So I find it strange that they don't resize themselves based on 'widget'.

It is the job of the layout to determine the size and position of the widgets. So if you explicitly resize a child widget which is inside a layout, you need to ensure that the new size is passed correctly through the layout system. This can be done by ensuring that the widget’s sizeHint() returns the new size. The value returned by the sizeHint() will be used when the layout calculates the new size. So after the sizeHint() has changed, simply call updateGeometry() [qt.nokia.com] that will notify the layout system that the widget has changed and may need to change geometry.
An alternative way to ensure that the parent widget is resized in response to its child being resized, is to call setFixedSize() on the child.
For more details check this...
http://qt-project.org/faq/answer/how_can_i_trigger_the_parent_widget_to_resize_when_its_child_widget_is_resi

You should let layout manage widgets size. As far as i am concerned there is 2 situations:
With layout when you are resizing a parent all children are resizing too regarding the size policy you provided to them. If you choose a fixed policy children will not be resized. So you have to resize them by hand... but it's quit weird.
When you are resizing a child like you are doing, parent is not automatically resized. You need to do it by hand. Fortunately there's a "magic function for that: AdjustSize. If you call it from QMainWindow all widget will be resized to their optimize size. It is possible (I can't test it here) that this does not work at runtime if size policy is set to fixed.
Hope that helps

Related

QWidget (a qlineedit) auto resize to content

Below Code successfully auto-resizes QLineEdit field as needed (new width/height based on dynamic text). Now in order to make the resized QLineEdit fit the container widget, I do adjustsize() on the container widget.
Relevant elements in my code:
void theContainer::resize_to_content(QString text) {
{
// ...
lineedit.setFixedSize(calcualtedWidth, calculatedHigh);
theContainer::adjustSize();
}
the problem encountered is that even though both resizings of the QLineEdit and the parent widget work (to some extent), the limitation in this case is that the QlineEdit, after resizing, overlaps adjacent widgets!
It looks like that container widget -- when it adjusts -- seems to ignore other non manipulated children ...
Is there a systematic way to prevent such overlapping ?? not just a workaround I mean.
-- Widgets before adjustments
-- Widgets after text change and size adjustments:
I'm pretty sure using the classes Qt provides specifically for layout management will help.
See Qt documentation on layout
If it won't, I think you could resize the entire window to get more space instead of only the parent widget.

Lay out an image on a Qt dialog

How to add an image to a dialog in Qt?
I know this has been often asked in the past and most answers come up with a QLabel and its setPixmap member. However, this usually is not what the user (me) intends:
A QLabel with a pixmap set does not participate in the surrounding QLayout. That is, it simply refuses to resize when the dialog is resized, like e.g., a QPushButton would do. Two QPushButtons next to each other in a QHorizontalLayout will (something like) equally divide the available horizontal space between them. A QLabe with a pixmap next to a QPushButton in the same layout will just stay fixed in size.
By default, a naked QLabel won't resize its contents when it's resized.
But when it does (QLabel::setResizeContents) it won't keep aspect ratio.
Is there any native way to have a pixmap shown on a dialog and have it reasonably participate in the layout?
Item resizing can be managed via sizePolicy property. From Qt documentation:
sizePolicy : QSizePolicy
This property holds the default layout behavior of the widget.
If there is a QLayout that manages this widget's children, the size
policy specified by that layout is used. If there is no such QLayout,
the result of this function is used.
The default policy is Preferred/Preferred, which means that the widget
can be freely resized, but prefers to be the size sizeHint() returns.
Button-like widgets set the size policy to specify that they may
stretch horizontally, but are fixed vertically. The same applies to
lineedit controls (such as QLineEdit, QSpinBox or an editable
QComboBox) and other horizontally orientated widgets (such as
QProgressBar). QToolButton's are normally square, so they allow growth
in both directions. Widgets that support different directions (such as
QSlider, QScrollBar or QHeader) specify stretching in the respective
direction only. Widgets that can provide scroll bars (usually
subclasses of QScrollArea) tend to specify that they can use
additional space, and that they can make do with less than sizeHint().
I think you are searching for QSizePolicy::Expanding size policy:
The sizeHint() is a sensible size, but the widget can be shrunk and
still be useful. The widget can make use of extra space, so it should
get as much space as possible (e.g. the horizontal direction of a
horizontal slider).
Set this for your QLabel and check how it will resize. Try other values from QSizePolicy::Policy enum.

Qt QGraphicsView - layout not shrinking & sizeHint, minimumSizeHint, etc. not called

I have the following, quite simple setup:
In a QWidget that is displayed as a window (no parent), there is a single QVBoxLayout.
In that QVBoxLayout, there is a single custom QGraphicsView.
The size policy of that custom QGraphicsView is set to Preferred/Preferred and setHeightForWidth set to true (and overwritten in the custom class) - I want to preserve aspect ratio.
The whole constructor of the widget here:
graphicsView = new CustomGraphicsView();
QVBoxLayout *layout = new QVBoxLayout();
layout->setMargin(0);
QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Preferred);
sp.setHeightForWidth(true);
graphicsView->setSizePolicy(sp);
layout->addWidget(graphicsView);
setLayout(layout);
The setup works, and the aspect ratio is maintained when dragging the width of the window bigger (the height grows with it).
But as soon as I drag the window width smaller, the aspect ratio of the graphics view is maintained, but the height of the window itself won't shrink. The result being a small graphics view with lots of space above and below it that shouldn't be there.
Investigating it further I was trying to find out where things break, so I overloaded all the sizeHint(), minimumSize(), minimumHeight(), etc. functions of my custom graphics view.
Just to discover that not a single one of them is ever being called while I am manually resizing the window. The only thing called as expected is heightForWidth - which returns my calculated value - but its return value is not applied when the window is shrinking.
So, not only do I not know why the layout won't shrink on its own despite having the Preferred vertical policy (which explicity says "The widget can be expanded, but there is no advantage to it being larger than sizeHint()").
I also don't know how the layout gets the size from the widget to begin with. I assumed sizeHint() since all of the documentation permanently refers to it, but that is obviously wrong in this case.
What I already tried is to set the vertical policy to every possible value. None of them would cause the window to grow and shrink as it is supposed to.
My current workaround:
I have added the resizeEvent(...) function to the widget and inside that, I manually resize() the whole widget if its height exceeds the value returned by the heightForWidth() function of the custom graphics widget.
Okay as far as workarounds go, but it leads to heavy flickering (as usual when resizing inside a resizeEvent).
Any ideas on either problem?

How to resize splitter widgets programmatically in Qt?

I use QSplitter to place some widgets side by side.
Being a user, I can resize those widgets just dragging a splitter.
Being a programmer, I don't know how to specify exactly what width and what height do I want at the moment.
That's my original state (adjusted by different stretches).
I tried to use setFixedSize(), but after that call the user can't resize widgets by itself anymore (and that's definitely correct behavior, because the size gets 'fixed').
If I use resize(), it has almost no effect. The widget is resized, but (!) incorrectly and (!) when I start dragging again the widget gets its initial state.
Is there any way to resize that left widget in code correctly? I don't want to have fixed size but resize() doesn't work properly, as you can see. So what should I do?
QSplitter hast its method QSplitter::setSizes(QList<int>) where each entry in the list is the size of the widget in pixels, from left to right or top to bottom respectively. The method does not require you to know the exact width, it still works with guessed sizes.
I use this functionality for instance to store the user defined sizes (obtained by QSplitter::sizes()) in a QSettings instance on the program shutdown and reapply them when the software is started again. If they are not set for some reason I just set the overall width divided by the number of widgets in the splitter and it works fine enough as an initial state.

Widget same size as it's children?

In Qt, how can I have a widget which automatically sizes itself according to the size of it's children?
For example, if I have a QGroupBox which contains a QHBoxLayout which contains some QPushButtons, I would like the QGroupBox to automatically calculate it's size so that it is no bigger and no smaller than necessary to fit all of the QPushButtons.
Ideally I would like to be able to do this in Qt Designer so that I can create a .ui file which already knows how to size the QGroupBox, however I am also opening to deriving from a class inside a .ui file and doing the resizing manually.
I have tried placing the QGroupBox inside it's own layout (with and without a spacer) but this just resizes the QGroupBox to the smallest possible size so that none of the children are visible.
There are two things to pay attention to:
Set the size policies appropriately on the children in the groupbox. You literally need to think what the buttons can do - most likely, you do not want the buttons to either grow or shrink, so setting both of their size policies to Fixed is the right thing to do. You could, possibly, let the buttons expand horizontally, so the horizontal policy of MinimumExpanding is an option.
Set the size constraint on the layout in the groupbox to act according to your objective:
ui->groupbox->layout()->setConstraint(QLayout::SetMinAndMaxSize);
Of course, the groupbox will be inside of some layout in its parent window, but that doesn't matter.
You'll probably have the most luck by sub classing QGroupBox and overriding sizeHint or other sizing functions to loop through children and calculate the minimum bounding rectangle. Depending on how dynamic the group box is, managing connections to new widgets might be a small challenge.