Change resize behavior in Qt layouts - c++

I want my custom widgets to gain extra space when the dialog is resized. This was working when I only had a handful of widgets, but after adding several more columns of these same widgets and putting them in a QGridLayout, the extra space merely goes in as padding between the widgets.

I've had trouble with this in the past and here are some of the things I've found:
First make sure all the widgets you want to expand have sizePolicy set to "Expanding".
Make sure the widgets that make up your custom widgets are in a layout that allows for expanding. You can check this by just adding one of your custom widgets to the window and seeing that it expands as expected.
Make sure any widgets on the form that you do not want to expand have a fixed (minimum=maximum) size in the dimension you want them to stay static.
Sometimes the grid layout causes some weird spacing issues because rows are resized based on the largest widget in the entire row and similarly for columns. For some layouts, it is better to use a vertical layout that contains horizontal layouts or vica versa to create a grid-like effect. Only this way, each sub-layout is spaced independently of the other rows or columns.

Controlling grid expansion programatically
I've found that you can easily control which columns/rows expand and which columns/rows stay fixed in width by using QGridLayout::setColumnStretch() and QGridLayout::setRowStretch(). You'll need to provide weights to the specific columns (0 for no stretch).
For example, if you want column 0 to not take up any room and column 1 to take the rest of the window's room, do this:
QGridLayout* layout ;
// Set up the layout
layout->setColumnStretch( 0, 0 ) ; // Give column 0 no stretch ability
layout->setColumnStretch( 1, 1 ) ; // Give column 1 stretch ability of ratio 1
Controlling grid expansion using Qt Designer
You can do what I described above if you're using Designer. Just look for the widget properties layoutRowStretch and layoutColumnStretch. It'll contain a comma-separated list of integers.

Another option is inside of QT Creator, to specify in the top level layout widget of the section you want fixed size a layoutSizeConstraint of "SetFixedSize". You must also remove all spacers from beneath that widget. In my case, I had a dialog with a TreeWidget, a Table, and some color selection stuff. I wanted the color selection controls to remain the same size horizontally, so they were in a VerticalLayout. I imagine you can do the same with a HorizontalLayout too if you want things to stay the same height. IF you really need spacers inside the layout, you can probably use blank labels with fixed size.

Related

How to make the sizes of groupboxes and the contents of a layout uniform

I have a few groupboxes inside of a gridlayout and also two Vboxlayouts that will contain widgets.
However I'm having trouble with the sizings of the groupboxes and the layouts as the layouts have a smaller horizontal size, what do I need to do to make them uniform?
Without much detail to go on in the question, my best guess is that for each QGroupBox in Qt Designer you want to set its sizePolicy -> Horizontal Policy to Expanding. This will make each group box take up the maximum amount of available horizontal space within its parent layout/widget. Which in turn should make them all the same overall width.

Qt Creator Resizing Widgets in Design Tab

I am having some difficulty resizing widgets inside a layout within the Qt Creator Design tab.
I want to have a vertical layout with a Grid Layout on the top part of the vertical layout and some buttons on the bottom of the vertical layout. When I set this up, the Grid Layout section and the Buttons section each take up exactly half of the screen as shown below.
Current Layout Screenshot
The design creator does not allow me to adjust the size of either section for some reason. I want to have the buttons only take up a small portion of the screen vertically (say 10%) and the Grid Layout take up the remainder of the screen (90%). How can I do that using the Qt Creator Design tab?
Just populate the top layout with a place holder widget that you can use as a container, and set its vertical size policy to MinimumExpanding. You should get something like this:
You can set size policies only on widgets, not on layouts. Therefore you can not achieve what you want without populating the top layout. Finally you can give the grid layout to the contents of the container widget.
Adjust the minimum size of your buttons if you want them to be higher.

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.

Qt GUI: Select multiple QLabels with mouse

I would like to enable mouse-selection of the text of several QLabels arranged in a grid layout in a Qt GUI.
A QLabel has textInteractionFlags like TextSelectableByMouse which enables this behaviour for one object, but a selection across several QLabel widgets does not seem to work.
Is there a way around this that does not require a lot of mouse "tracking" or reimplementing a layout?
I fear there's no simple method to get what you want. The first problem would be what you'd expect to find in the paste buffer after selecting some rectangular section of your table. How should the label texts be delimited, should they be organized by row or colum?
You may say that you want them row-wise, columns separated by blanks and rows ending with a \n, but that doesn't need to be what the next person needs.
You may want to spend some time considering QTableView or QTableWidget.

QListWidget that resizes instead of scrolls

How do you change the behavior of a QListWidget so that it resizes its height instead of choosing a (seemingly arbitrary) height and adding scrollbars? See screenshot:
The QListView's should fill up as much space horizontally as they can (creating as many "columns," if you will.) Then they wrap and make as many rows as necessary to fit all the items. These calculations should be adjusted as the window is resized. This is all working fine.
However, what I want to happen is that instead of the height staying the same, the QListView should grow or shrink vertically and never need any scrollbars. The scrolling, if necessary, will be handled on the parent QWidget that hosts all of the labels and lists. It seems like once the height of the QListWidget is established (not sure where its default is coming from), it never changes. It is too big in some cases (see second "Test" list above) and too small in others (see first "blank maps" list above.)
The layout above is nothing surprising: two QLabel's and two QListWidget's in a QVBoxLayout. Here are the properties I have set on the QListWidget's:
setMovement(QListView::Static);
setResizeMode(QListView::Adjust);
setViewMode(QListView::IconMode);
setIconSize(QSize(128, 128));
(I already tried setting the horizontal and vertical scrollbar policies, but that just turns the scrollbars off, clipping the content. Not what I want.)
Maybe you could this without using QListWidget. The Qt's examples contain a new layout class, QFlowLayout, which could be useful. With the following kind of widget hierarchy you could get multiple groups with labels and they all would be inside one QScrollArea.
QScrollBox
QVBoxLayout
QLabel "Blank maps"
QWidget
QFlowLayout
your own widgets showing map images and labels
QLabel "Text"
QWidget
QFlowLayout
your own widgets
The problem is that this kind of solution would create much more widgets than QListWidget based solution. So if you have hundreds of items in your list, this might not be the best solution.
There is a protected member function called contentsSize() in QListView. It is used to calculate the required minimum(), maximum(), and pageStep() for the scrollbars (as mentioned here).
Can you subclass the QListView class and make use of that information? I suggest you recalculate the size of your widget in the same function where you add contents to it. While somewhat lacking elegance, this appears to be a pretty reliable solution.