PDA

View Full Version : Arranging widgets inside widgets and automatic re-sizeing.



Bobruisk
25th April 2013, 08:47
Hi everyone,

I'm new to the forum, and pretty much new to Qt. I would like some tips on how I can create the widget layout I'm looking for.

Intention
I have a widget, DisplayArea, which is pretty much only a frame. I want it to have a fixed width, but want to be able to re-size it vertically. Inside this area I want to add one or many widgets which are of the same width as the DisplayArea, but may be of any height. The widgets may also change size during runtime (clicking hide/show on information, etc). I want the DisplayArea to at all times be of just enough size to contain these sub-widgets.

For example, DisplayArea with one sub-widget, displaying a name


________________
|Name: Bobruisk|
^^^^^^^^^^^^^^


Now I may add another widget containing a button to the display area:


________________
|Name: Bobruisk|
| <BUTTON> |
^^^^^^^^^^^^^^


When this button is clicked, I want it to expand the sub-widget, and the DisplayArea, so that some hidden information is shown;


________________
|Name: Bobruisk|
| <BUTTON> |
| Address: |
| Bobroad 2 |
| 123 53 |
| Bobruisk |
| Ukraine |
^^^^^^^^^^^^^^


If the button is clicked again, the adress information should hide again, and the widgets be re-sized to what they were before.

What I have done so far
All done in Qt Designer:
I have created a DisplayAreaWidget which is is a QFrame. I have changed all the margins in the default layout to 0 so that the sub-widgest should stack tightly.

I have created the Name-widget (First line placed inside the DisplayArea). It is a QWidget containing a single QLineEdit.

I have created the Adress-widget (With the button that shows/hides adress). It is a QWidget containing a QPushButton (togglable) and a QLineEdit (Placeholder). I have connected the toggled signal to the show slot of the QLineEdit. The showing/hiding works just fine.

Problems
I have a couple of problems that I am unable to resolve.

First, when I create the Name and Adress widgets with the DisplayArea as parent, they do not get a nice layout. The AdressWidget goes pretty much on top of the NameWidget. I create them using the DisplayArea as parent in the QWidget constructor.

Second, the AdressWidget does not automatically re-size when information is hidden/shown. When the data is hidden, the button is large. When data is shown, the button is smaller. It seems the widget itself is of constant size, but the components (QPushButton /QLineEdit) are re-sized instead.

So;

how can I make the sub-widgets (Name/Adress/...) arrange nicely under eachother?
how can I make the widgets re-size so that they are just large enough to hold their contents?

I hope I've managed to make my question clear. I'll clarify, if needed :)

Thanks for any assistance!

//Bobruisk

Santosh Reddy
25th April 2013, 09:41
how can I make the sub-widgets (Name/Adress/...) arrange nicely under eachother?
Use QVBoxLayout


how can I make the widgets re-size so that they are just large enough to hold their contents?
Set the vertical size policy as QSizePolicy::MinimumExpanding, and horizontal size policy as QSizePolicy::Fixed for all top level widget, this will ensure that the when top level widget increases vertically all the child widgets all increase, but when top widget is decreasing in vertical size it only decrease to a size where all child widgets will fit snugly. There will only one issue with this when a child widget is hidden using button click, the top level widget will not decrease it's size, you need to write some extra code to decrease it's size.

ChrisW67
25th April 2013, 09:45
Extension Example

Bobruisk
25th April 2013, 09:46
Thanks for your reply. I will try this. One question about the layouts. When I use the designer and simply create a QFrame, there seems to be some kind of layout that is part of the QFrame object. What is this? I tried dragging widgets into the QFrame and they seem to align themselves nicely vertically. There are also settings for the layout when I select the QFrame. Is this some other kind of layout, other than a QVBoxLayout?


Use QVBoxLayout


Set the vertical size policy as QSizePolicy::MinimumExpanding, and horizontal size policy as QSizePolicy::Fixed for all top level widget, this will ensure that the when top level widget increases vertically all the child widgets all increase, but when top widget is decreasing in vertical size it only decrease to a size where all child widgets will fit snugly. There will only one issue with this when a child widget is hidden using button click, the top level widget will not decrease it's size, you need to write some extra code to decrease it's size.

ChrisW67
25th April 2013, 10:13
You can apply a layout to any container widget in Designer. You choose what the layout is; vertical, horizontal, grid, etc.

Bobruisk
25th April 2013, 10:22
In the Qt Designer there are 4 layouts available in the Widget Box.

What is the difference between:

1: Creating a QFrame which seems to contain a vertical layout by default
and
2: Creating a QFrame, then creating (drag drop) a vertical layout from the Widget Box
?

Isn't the second creating a layout within the layout?

//Bobruisk

Santosh Reddy
25th April 2013, 10:37
In the Qt Designer there are 4 layouts available in the Widget Box.

What is the difference between:

1: Creating a QFrame which seems to contain a vertical layout by default
and
2: Creating a QFrame, then creating (drag drop) a vertical layout from the Widget Box
?

Isn't the second creating a layout within the layout?
This is not expected behavior, I think you are missing somthing.

BTW what is the version of Qt Designer you are using for this?

Bobruisk
25th April 2013, 11:09
This is not expected behavior, I think you are missing somthing.

BTW what is the version of Qt Designer you are using for this?

I'm using Qt and Qt Designer 4.7.4.

I should clarify what I mean with what I said above.

If i create a QFrame (as the main widget, the only widget), select it, and look in the property editor I see some layout parameters in the bottom. It has a name, left/top/right/bottom margin, spacing, stretch and sizeConstraints.

I opened the uic'ed file and found these lines (can't copy paste so typos may occur);



class Ui_displayArea
{
QVBoxLayout * verticalLayout;
...
void setupUI(QFrame *displayArea)
{
...
verticalLayout = new QVBoxLayout(displayArea);
...
}
};


So it seems there is a QVBoxLayout created. Do I need to activate it somehow?

What happens in my code, step by step:


I create the DisplayArea. setupUI is called, the verticalLayout is created.
I create the NameWidget with the DisplayArea as parent.
I create the AdressWidget with the DisplayArea as parent.


The AdressWidget appears on top of the NameWidget. :(

If I drag-drop stuff into the DisplayArea from Qt Desinger, they align themselves nicely. But when I add widgets dynamically like this, they do not follow the layout.

Santosh Reddy
25th April 2013, 12:24
As I said QFrame does not have default layout, unless a layout is explicitly selected.

Here is screenshot from my version
8987

Bobruisk
25th April 2013, 12:33
I created a QFrame as the base widget or what to say. That is, new -> QFrame. Then it comes with a layout.

I found what was going wrong for me, anyway. I thought that creating a new QWidget with a parent automatically adds the widget to the parent's layout. Apparently, I need to do


parent->layout()->addWidget(newWidget);

I have created a signal that the AdressWidget emits whenver it changes layout (show/hide), so that the DisplayArea is resized at that time. This seems to be working, except it does not automatically resize until I press the show/hide button once. I'll have a look at this, and return if I run into problems.

Thanks for your help!

//Bobruisk

Santosh Reddy
25th April 2013, 13:29
I created a QFrame as the base widget or what to say. That is, new -> QFrame. Then it comes with a layout.
I did a new->QFrame and this is my designer screenshot

8988


I found what was going wrong for me, anyway. I thought that creating a new QWidget with a parent automatically adds the widget to the parent's layout.
Creatig a new QWidget with a prarent will add it to the parent's child list but will not add it to the layout. You need to add it explicitly as you figurred it out.

Bobruisk
25th April 2013, 13:58
Strange, I did the new->QFrame on another computer (this one) and I get the same result as yours. Anyway, now it is working. No need to delve into these mysteries :)