Resizing a QDialog after adding components to a child widget - qt

I'm a bit new to QT but have to work on existing code. Here's the case:
I have a class extending QDialog. the constructor sets a QGridLayout then adding three other widgets to it. One of the widgets is a QScrollArea containing a QGroupBox. this QGroupBox has a QVBoxLayout and there I'm adding a list of widgets at runtime. The size of the scroll area should grow until a given limit is reached before showing the scrollbars so that they are only used when the dialog would grow too high. I've found that the sizeHint of the outer layout doesn't update when the sizeHint of the scroll area updates. How can I refresh this, or is there a better way to resize the parent dialog?

What about using widgetResizable property of QScrollArea? It should try to resize view to avoid using scorllbars.

Related

Why won't QGroupBox widgets dynamically resize with rest of window?

I have a QMainWindow with the widgets laid out in a grid. They all resize proportionally when the window resizes as expected, except for the widgets placed inside a QGroupBox. The QGroupBox itself resizes, but the widgets inside just stay on the same place. If I apply a lay out on the QGroupBox, the widgets loose their original positions. Note that I'm using the .ui file with PyQt4. You can get the file here.
And this is what happens:
From Qt documentation on QGroupBox:
QGroupBox doesn't automatically lay out the child widgets (which are
often QCheckBoxes or QRadioButtons but can be any widgets).
There is an example showing how to setup a layout for a QGroupBox (which is the same a setting up a layout for any QWidget based object meant to store other objects, like QFrame for instance).
You must create a layout, call QGroupBox::setLayout and then add widgets to the layout. If you use QtCreator, right-click the QGroupBox and select the layout you want to use for it from the context menu.

QT layout manager does not recover space when hiding widget until window is moved

I am using Qlabels to plot some graphs and images (via setpixmap).
My basic layout is:
QVBoxlayout main layout via qdialog's setlayout.
QHboxlayout (array of QLabels)
Qlabel expandedPlot (optional expanded plot of one of the above QLabels)
QLabel mainImage Main image display
Within the QDialogs re-implemented keypress event handler, I hide()/show() the expanded plot. When I hide() the expandedPlot, the layoutmanager recovers about 1/2 of the vertical usage. Then when I drag the window, the layout manager recovers the remainder of the vertical space (as if there was no item present).
How can I force the behavior of moving the window? I want the layout manager to completely recover the vertical space.
I am using Qt 5.6 on windows, but want cross-platform solutions.
Thank you, mike
Because laying out the widget is quite expensive, Qt doesn't always do it. If you change the size of enclosed widgets you are likely to need to call updateGeometry on them to trigger the enclosed layout manager to re-layout. But if you hide the widget, updateGeometry does nothing. In that case you need to call adjustSize on the parent widget, which will then trigger the re-layout.

Qt ScrollArea on widget messes up size and position of widget [Qt 5.1]

I'm new with Qt and I want to implement a scrollable widget which can grow dynamically, e.g. by adding buttons into it when another button is pressed. I try to implement it using the following layout and code:
scrollArea = new QScrollArea(ui->outerWidget);
scrollArea->setWidget(ui->innerWidget);
layout = new QVBoxLayout(ui->outerWidget);
ui->innerWidget->setLayout(layout);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// code for PushButton to add buttons in innerWidget
void MainWindow::on_pushButton_clicked()
{
QPushButton *button = new QPushButton("button"+QString::number( nameCounter ));
nameCounter ++;
ui->innerWidget->layout()->addWidget(button);
}
This implementation has two problems when I run the program, first the innerWidget appears out of place (I define its position in Qt Creator's Design mode) and second after many widgets are added in the layout the scroll bar is doesn't grow, but instead the widgets are become smaller to fit into the layout:
In another thread it was suggested to set widgetResizable to true:
scrollArea->setWidgetResizable(true);
The scroll bar seems to work now but the new problem is that the innerWidget becomes very small so it is barely visible:
So, how can I achieve a scrollable widget that will respect the size and position of the design?
have no environment to verify but good luck.
to place scrollArea the target position,
Manually call SetGeometry, or
Place a QScrollArea in ui form, (suggested if it's static), or
Place a widget in your target position, and set QScrollArea's parent to it, and add QScrollArea to its layout, and Set QScrollArea to be expanding.
manually create a QWidget innerWidget and assign it to scrollArea via QScrollArea::setWidget(*QWidget), try different size policy to innerWidget, such as "Preferred".
Also be aware of Qt's reference mentioned : void QScrollArea::setWidget ( QWidget * widget )
Sets the scroll area's widget.
....
Note that You must add the layout of widget before you call this function; if you add it later, the widget will not be visible - regardless of when you show() the scroll area. In this case, you can also not show() the widget later.
Above list solutions, below are reasons to the problems you mentioned:
scrollArea->setWidget(ui->innerWidget); Setting a widget to ScrollArea will change the parenting and layouting of ui->innerWidget, so the geometry values written in ui form (in Qt Creater) will no longer take effect, this is the reason of innerWidget out of place. ui->innerWidget is no longer a child of outerWidget, it's geometry will follow its new parent (but not scrollArea, there's some tricky layouting inside QScrollArea". To be clear, innerWidget is not helpful to locate scrollArea in such scenario.
In your first clip of code, widget 'scrollArea' is created with parent outerWidget, again no size policy or layout or geometry is specified, so scrollArea will by default be placed at the left top corner of the parent "outerWidget". To place scrollArea to your target geometry, you can " set geometry manually " or " assign innerWidget as scrollArea's parent and expand scrollArea". Obviously the latter method cannot assign ui->innerWiget to scrollArea->setWidget().
scrollArea->setWidgetResizable(true); makes the scrollArea "shrink" at left top corner of outerWidget. This is because, QScrollArea does not increase along with it's contents, it can scroll to display all of it contents so the required size of QScrollArea can be as small as possible. Once the 'Resizable' property is set to "true", QScrollArea decides to shrink to its minimum necessary size, thus the size to display its scroll bar and scroll buttons....

How to prevent QTableWidget from occupying the whole window in a QHBoxLayout?

In my Qt program, I programmatically generate a modal QDialog. I want to show two widgets in this dialog window: A custom widget showing a camera output and a QTableWidget, showing the pixel coordinates of the corners found in the camera image. I generate a QHBoxLayout and add my custom widget and the QTableWidget into it. Then I set this QHBoxLayout as the Layout of the QDialog window. What I want to achieve is to share the available space in the QDialog's window area equally between my custom QWidget and the QTableWidget, horizontally, by using a QHBoxLayout. But I always end up with QTableWidget occupying the whole QDialog area, by overlapping my custom widget. How can I instruct these two widgets to exactly share the QDialog area?? Note that I first add my custom widget and then the QTableWidget into the QHBoxLayout.
Make sure on your custom widget you've specified a minimumSizeHint and a sizeHint, this instructs the QLayout manager that the widget requires a specific space. To have them split equally you'll be best off detecting the size of the QDialog and then specifying the width for both by removing the boundary sizes (spacing between widgets + space to QDialog edge) and dividing it up.

QT Layout - initial directions

I am new to QT. I'm trying to understand the layout mechanism by trying to implement this small window seen below. It has the following elements under the QWidget that's the main window:
One big QWidget that stretches on all the client area.
Two QWidget containers on the top of the window. Both should have the same height, but the right one stretches horizontally, as the window grows/shrinks.
one button container widget on the top right, with fixed height and width
Large QWidget container filling the rest of the client area, that should resize as the window resizes.
The parent window itself is resizeable.
I'm looking for hints as to what layout I should use. How do I achieve this programatically? define what stretches automatically, what stays with a fix size? and how the proportions are kept where they need to be kept.
I'd appreciate any pointer you may have.
The easiest, and IMHO best, way to accomplish this is via the QHBoxLayout and QVBoxLayouts. You can do this via the designer in QtCreator, but I find it doesn't work perfectly if you need to adapt things over time. If it's a static set of widgets, I do suggest designing it using the QtCreator designer as it'll greatly simplify your life.
If you're going to do it programatically, the main window should be set to use a QVBoxLayout and then two sub-QVBoxLayout's after that, where the bottom one is configured to take any space it can get. Then in the top QVBoxLayout, add a QHBoxLayout with your two upper components.
to set a widget to fixed size in code you call setFixedSize( int h, int w ) on the widget. To do it in Designer click on the widget and look in the property editor in the QWidget section. open the sizePolicy thingy and set horizontal and/or vertical to fixed. Then open Geometry and set the width and Height.
To make them stretch at different ratios in code you use a separate argument when using a box layout. eg layout->addWidget( button1, 1 ); layout->addWidget (button2, 2); this would cause button2 to expand at twice the rate of button1. To do this in designer, open the sizePolicy property of the widgets and set the HorizontalStrech and/or VerticalSretch. Note that the size policy needs to not be Fixed in this case for the direction you want to set the stretch on. Also it will never let a widget shrink below its minimum size (it would rather mess up the ratio than shrink something too small).

Resources