Chapter 4. Tutorial: Using Layout Management

Table of Contents
Putting A Form Together With Layouts
Popular Mechanics: Working With Spacers

Let's start this tutorial with a simple truth: Each form in each application needs to be layouted. You might not have given this much thought, but when you created the pizza entry form in the previous tutorial, you were actually layouting the dialogs: You decided where to put the individual widgets, which size they should get, and so on.

Perhaps you thought that this was not much of a problem, but doing the layouts this way by hand leads to a number of problems:

Hopefully, you are now convinced that hand-crafted layouts are not the way to go. But what is the alternative? Qt provides a sophisticated layout system that does all the layouting for you. If you want to program layouts using this system directly, then you have to learn quite a lot and follow a number of rules, but with Qt Designer, using automated layouts is quite intuitive.

Putting A Form Together With Layouts

In this section, we will create a form that resembles the one we did in the previous tutorials, but will use automatic layout management. The final form will look strikingly similar to the one you already created, but behave a lot better with respect to the aforementioned problems. Also, you will see that the design goes actually faster with layout management once you get used to it.

Let's take a fresh start and begin with an empty form. Start Qt Designer if it is not yet running and click on the icon for creating a new form. Select Dialog as the form type.

Again, we start with the toppings, but this time we will begin with the button group right away and just put the checkboxes on top of it. So, select the button group tool and insert a button group. Give it the text Toppings and make it large enough so that you can put four checkboxes onto it without problems. You can even make it really huge, we will have it resized automatically later.

Now, select the checkbox tool and put a checkbox onto the button group. Change the label to Champignons. Repeat the process with three more checkboxes labelled Ham, Pineapples, and Anchovis, respectively. You do not need to take any care about alignments or such, just put the four checkboxes roughly below each other. When you are done, your form might look like in Figure 4-1.

Figure 4-1. The checkboxes are not layouted yet

Now we want to layout this button group with its four checkboxes. This requires some thinking. Automated layouting in Qt is always done with respect to a container; you could say that it is the container that is layouted. In practice, the container is just any widget that happens to have widget children, so there is nothing special about containers.[1] Just remember that when you want to arrange a few widgets like in our case the four checkboxes, the layouting process does not apply to the widgets but to their container (parent) — in our case the button group.

The next thing to think about is which kind of layout you want. Qt currently provides three different kinds of layout managers: one that arranges the widgets horizontally, i.e., in a row, one that arranges the widgets vertically, i.e., in a column, and one that arranges the widgets both horizontally and vertically, i.e., in a grid. You can also combine different layout managers to achieve the desired result, for example, you might often find the grid layout managers layout policy a bit too restrictive and resort to putting together some rows and columns which gives you much more flexibility at the price of a bit more work.

For our button group with the four checkboxes it is obvious that we want a vertical layout, i.e., that we want to arrange the checkboxes in a column. And we also know now that we need to apply the layout to the button group, not to the checkboxes themselves. So, to put all this together, click on the background of the button group widget and select Layout/Layout Vertically, click on the vertical layout button on the taskbar (see Figure 4-2) or select Layout Vertically from the button group's context menu. Magically, all the buttons are aligned, and the button group has exactly the size it needs to accomodate the buttons (see Figure 4-3).

Figure 4-2. The vertical layout icon

Figure 4-3. The checkboxes are now layouted in the button group

Assigning a layout has some other consequences: If you know click on one of the checkboxes, you will see that the handles are no longer black, but grey. If you try, you will also notice that you can no longer move or resize the checkboxes. This is because the column layout manager that you have assigned to the button group has taken over the responsibility for assigning sizes and positions to the layouted widgets. If you look very closely at the property editor, you will also notice that the property geometry has disappeared from it — again, because you cannot change it any longer.

If you want to change sizes or positions of the layouted widgets again, you have to remove the layout manager. This is called breaking the layout. You do this by selecting Layout/Break Layout from the menubar, Break Layout from the context menu of the button group or by clicking on the toolbar button for breaking the layout (see Figure 4-4).

Figure 4-4. The “break layout” icon

You might want to try the other layout managers as well. Break the column layout and assign a row layout instead (see Figure 4-5). You can also try a grid layout, but you will not see much good in this situation; we will explain later why. However, when you do these experiments, it is good to know that you can always go back with the undo button (see Figure 4-6) or by selecting Edit/Undo from the menubar. With the undo and redo functionality, you can explore various options for your forms without committing to anything that you cannot take back later.

Figure 4-5. Arranging the checkboxes in a row

Figure 4-6. The undo icon

When you are done trying various things with the toppings button group, restore the state of Figure 4-3 and start working on the button group for the pizza size. You should put it somewhere to the right of the toppings button group, but again, you do not have to worry about alignments yet; this will be taken care of automatically later. When you are done, assign a vertical layout to the size button group as well. Your form should now look roughly like in Figure 4-7.

Figure 4-7. Two layouted button groups

Now finish putting elements onto the form by inserting the extra cheese checkbox and the OK and Cancel push buttons. Put them roughly where they were in the previous form. Your form should now look like in Figure 4-8.

Figure 4-8. More widgets to be layouted

At this point, you could say that we have five different elements on the form: the two button groups, the extra cheese checkbox and the two push buttons. At this stage, we do not care about the fact that the button groups actually are compound elements as well, they are layouted and done, we just consider them elementary widgets for the time being. But know we want to layout these five elements. This is a typical situation when designing a form with Qt Designer: The idea is to do the design in two different stages: First, you put all the widgets onto the form and assign them the desired properties, then you layout them by assigning layout managers. Of course, in evolutionary development, you will go back to stage one now and then (this often means breaking layouts), add, remove, or change some widgets and then go back to layouting. The distinction between the two phases is more a conceptual one than one that is enforced by the program.

We might be able to arrange the five elements into a grid, but this would probably look unnatural. Instead, we will try to find a good combination of rows and columns. There are not so many rules for doing this, you basically learn this by doing, experimenting, and looking at other peoples' well-designed dialogs (or learning from the mistakes being made in the not-so-well-designed dialogs). But one common theme in dialog design is that the main orientation is vertical, i.e., that the dialog consists of a number of rows that are layouted on top of each other. Sometimes, the rows have some internal vertical structure as well, and sometimes these internal vertical structures have a horizontal structure, but this is already rather rare.

If you look at your form in its current state, you might already see this pattern: We could assemble the two button groups in a row, leave the extra cheese checkbox on a row by itself, and put the two push buttons in a third row. Then, we just put these three rows in top of each other in a vertical layout.

Let's start following this plan by putting the two button groups in a row. Earlier, you learned that layout managers are always applied to a container, and it is difficult to see a suitable container for the two button groups here. The only parent that they have is the form as a whole, and this will not work, because assining the form a row layout manager would mean that all five components would be put in one row, which is certainly not what we want.

Luckily, we can just select the widgets that we want to be layouted and select a layout manager for them, and Qt Designer will automatically provide an invisible Reggie: are those nested layouts or real Thus, click on the left button group, hold the shift key and click on the second button group so that these two (and nothing else) are selected. Now use any of the meanas described above to assign a horizontal layout manager. The two button groups will be aligned, and a thin red frame indicates the invisible container that was created to hold the row layout manager (cf. Figure 4-9).

Figure 4-9. A new layout manager was created for the button groups

Now do the same with the two push buttons. With these steps, the elements to be layouted have been reduced to three, the two layouted rows and the single checkbox in between. It is not necessary at this point to put the checkbox into a row all by itself.

Next, select the form itself by clicking on the background and assign a vertical layout. This will arrange the remaining three pieces, the row with the two button groups, the extra cheese checkbox and the row with the push buttons on top of each other. Now all the widgets are nicely grouped together as you can see in Figure 4-10. Some things might not be perfect (for example, the extra cheese checkbox should be centered below the button groups), but we'll fix that later.

Figure 4-10. All widgets are arranged

To test the dialogs correct behavior while resizing, go into test mode as described previously and try resizing the dialog. See how the space is distributed amongst the widgets. Also notice that you cannot make the dialog smaller than the minimum size needed to accomodate all the widgets.

Notes

[1]

Unlike in e.g. the Java AWT where a distinction is made between containers and components, and only containers can contain other containers and components and be layouted.