1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
<title>Tutorial: Using Layout Management</title>
<meta name="generator" content="Adobe GoLive 4">
<link rel="HOME" href="book1.html">
<link rel="UP" title="Qt Designer Tutorial and User's Manual" href="part1index.html">
<link rel="PREVIOUS" title="Connecting Widgets To Each Other" href="chap3_4.html">
<link rel="NEXT" title="Popular Mechanics: Working With Spacers" href="chap4_2.html">
</head>
<body class="CHAPTER" bgcolor="white" text="black" link="blue" vlink="#840084" alink="blue">
<div class="NAVHEADER">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td width="500" align="left" valign="middle"><img height="90" width="475" src="figures/title.png" border="0"></td>
<td></td>
<td align="right" valign="top"> <a href="../company/about/trolls.html">
<table border="0" cellpadding="0" cellspacing="0" width="137">
<tr>
<td><img height="100" width="100" src="figures/f001.png" border="0"></td>
<td><img height="100" width="100" src="figures/qtlogo.png" align="top" border="0"></td>
</tr>
</table>
</a></td>
</tr>
<tr>
<td width="500"><spacer type="block" width="500" height="20"></td>
<td><spacer type="block" width="42" height="20"></td>
<td><br>
</td>
</tr>
</table>
<table width="100%" border="0" cellpadding="3" cellspacing="0" bgcolor="black">
<tr>
<td width="10%" align="left" valign="bottom"> <a href="chap3_4.html"><img height="20" width="20" src="arrows/left.png" border="0"></a></td>
<td width="80%" align="center" valign="bottom"><br>
</td>
<td width="10%" align="right" valign="bottom"> <a href="chap4_2.html"><img height="20" width="20" src="arrows/right.png" border="0"></a></td>
</tr>
</table>
</div>
<div class="CHAPTER">
<h1><a name="AEN678"></a>Chapter 4. Tutorial: Using Layout Management</h1>
<div class="TOC">
<dl>
<dt><b>Table of Contents</b>
<dt> <a href="#AEN699">Putting A Form Together With Layouts</a>
<dt> <a href="chap4_2.html">Popular Mechanics: Working With Spacers</a>
</dl>
</div>
<p>Let's start this tutorial with a simple truth: Each form in each application needs to have a layout. You might not have given this much thought, but when you created the pizza entry form in the previous tutorial, you were actually laying out the dialogs: You decided where to put the individual widgets, what size they should be, and so on.</p>
<p>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:</p>
<ul>
<li>
<p>The layout process gets increasingly difficult in larger dialogs.</p>
<li>
<p>If the form is a dialog, it will not resize correctly. Once the user resizes the dialog, your carefully crafted layout is shredded to pieces. Of course, you can make the dialog non-resizable, but it is very likely that your users will not be too happy about this.</p>
<li>
<p>If you want to internationalize your program, your handcrafted layouts will not work either. Internationalizing a program means preparing it for translation, and you only do this if you expect there to be translations later. But translations, especially from English to other languages, have the nasty property that the translated text is often longer than the original text. Think of a check box whose label has become larger after translating: The check box might not be large enough to accommodate its own label, and even if it could magically resize itself somehow, the check box would no longer fit in the surrounding group box, and so on.</p>
<li>
<p>If you want to allow the user to run the program with different application fonts, then all the problems just described apply as well.</p>
<li>
<p>And finally, the same goes if you want to be able to switch widget styles dynamically (or let the user do so); i.e., you do not want to hardcode the widget style.</p>
</ul>
<p>Hopefully, you are now convinced that handcrafted layouts are not the way to go. But what is the alternative? Qt provides a sophisticated layout system that does all the laying out 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 automatic layouts is quite intuitive.</p>
<div class="SECT1">
<h1 class="SECT1"><a name="AEN699"></a>Putting A Form Together With Layouts</h1>
<p>In this section, we will create a form that resembles the one we did in the previous tutorials, but we will use automatic layout management. The final form will look strikingly similar to the one you already created but will behave a lot better with respect to the aforementioned problems. Also, you will see that the design actually goes faster with layout management once you get used to it.</p>
<p>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 <span class="GUILABEL">Dialog</span> as the form type.</p>
<p>Again, we start with the toppings, but this time we will begin with the button group right away and just put the check boxes on top of it. So, select the button group tool and insert a button group. Give it the text <span class="GUILABEL">Toppings</span> and make it large enough so that you can put four check boxes onto it without problems. You can even make it really huge; we will have it automatically resized later.</p>
<p>Now, select the check box tool and put a check box onto the button group. Change the label to <span class="GUILABEL">Mushrooms</span>. Repeat the process with three more check boxes, labeled <span class="GUILABEL">Ham</span>, <span class="GUILABEL">Pineapple</span>, and <span class="GUILABEL">Anchovies</span>, respectively. You do not need to be careful about alignment; just put the four check boxes roughly below each other. When you are done, your form might look like the one in <a href="#QT-DESIGNER-FIG-LAYOUTTUTSTEP1">Figure 4-1</a>.</p>
<div class="FIGURE">
<a name="QT-DESIGNER-FIG-LAYOUTTUTSTEP1"></a>
<p><b>Figure 4-1. The check boxes are not laid out yet</b></p>
<p><img src="figures/layouttutstep1.png"></p>
</div>
<p>Now we want to lay out this button group with its four check boxes. This requires some thinking. Automatic laying out in Qt is always done with respect to a container; you could say that it is the container that is laid out.
In practice, there is nothing special about containers: any widget that happens to have child widgets is a container. Just remember that when you want to arrange a few widgets—like the four check boxes in our case—the layout process applies not to the widgets but to their container (parent)—in our case the button group.</p>
<p>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 (in a row), one that arranges the widgets vertically (in a column), and one that arranges the widgets both horizontally and vertically (in a grid). You can also combine different layout managers to achieve the desired result; for example, you might often find the grid layout manager's layout policy a bit too restrictive and resort to putting together some rows and columns, which gives you much more flexibility for the price of a bit more work.</p>
<p>For our button group with the four check boxes, it is obvious that we want a vertical layout; i.e., that we want to arrange the check boxes in a column. And we also know now that we need to apply the layout to the button group, not to the check boxes themselves. So, to put all this together, click on the background of the button group widget and select <span class="GUIMENU">Lay Out/Lay Out Vertically</span>, click on the vertical layout button on the toolbar (see <a href="#QT-DESIGNER-ICON-VLAYOUT">Figure 4-2</a>), or select <span class="GUIMENU">Lay Out Vertically</span> from the button group's context menu. Magically, all the buttons are aligned, and the button group has exactly the size it needs to accommodate the buttons (see <a href="#QT-DESIGNER-FIG-LAYOUTTUTSTEP2">Figure 4-3</a>).</p>
<div class="FIGURE">
<a name="QT-DESIGNER-ICON-VLAYOUT"></a>
<p><b>Figure 4-2. The vertical layout icon</b></p>
<p><img src="figures/vlayout.png"></p>
</div>
<div class="FIGURE">
<a name="QT-DESIGNER-FIG-LAYOUTTUTSTEP2"></a>
<p><b>Figure 4-3. The check boxes are now laid out in the button group</b></p>
<p><img src="figures/layouttutstep2.png"></p>
</div>
<p>Assigning a layout has some other consequences: If you now click on one of the check boxes, you will see that the handles are no longer black but gray. If you try, you will also notice that you can no longer move or resize the check boxes. 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 laid out widgets. If you look very closely at the property editor, you will also notice that the property <tt class="LITERAL">geometry</tt> has disappeared from it—again, because you cannot change it any longer.</p>
<p>If you want to change the sizes or positions of the laid out widgets again, you have to remove the layout manager. This is called <i class="EMPHASIS">breaking the layout</i>. You do this by selecting <span class="GUIMENU">Lay Out/Break Layout</span> from the menu bar, by selecting <span class="GUIMENU">Break Layout</span> from the context menu of the button group, or by clicking on the toolbar button for breaking the layout (see <a href="#QT-DESIGNER-ICON-BREAKLAYOUT">Figure 4-4</a>).</p>
<div class="FIGURE">
<a name="QT-DESIGNER-ICON-BREAKLAYOUT"></a>
<p><b>Figure 4-4. The break layout icon</b></p>
<p><img src="figures/breaklayout.png"></p>
</div>
<p>You might want to try the other layout managers as well. Break the column layout and assign a row layout instead (see <a href="#QT-DESIGNER-FIG-LAYOUTTUTSTEP3">Figure 4-5</a>). You can also try a grid layout, but you will not see much good in this situation; we will explain why later. However, when you do these experiments, it is good to know that you can always go back with the undo button (see <a href="#QT-DESIGNER-ICON-UNDO">Figure 4-6</a>) or by selecting <span class="GUIMENU">Edit/Undo</span> from the menu bar. With the undo and redo functionality, you can explore various options for your forms without committing to anything that you cannot take back later.</p>
<div class="FIGURE">
<a name="QT-DESIGNER-FIG-LAYOUTTUTSTEP3"></a>
<p><b>Figure 4-5. Arranging the check boxes in a row</b></p>
<p><img src="figures/layouttutstep3.png"></p>
</div>
<div class="FIGURE">
<a name="QT-DESIGNER-ICON-UNDO"></a>
<p><b>Figure 4-6. The undo icon</b></p>
<p><img src="figures/undo.png"></p>
</div>
<p>When you are done trying various things with the toppings button group, restore the state of <a href="#QT-DESIGNER-FIG-LAYOUTTUTSTEP2">Figure 4-3</a> 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 alignment yet; this will automatically be taken care of later. When you are done, assign a vertical layout to the size button group as well. Your form should now look roughly like the one in <a href="#QT-DESIGNER-FIG-LAYOUTTUTSTEP4">Figure 4-7</a>.</p>
<div class="FIGURE">
<a name="QT-DESIGNER-FIG-LAYOUTTUTSTEP4"></a>
<p><b>Figure 4-7. Two laid out button groups</b></p>
<p><img src="figures/layouttutstep4.png"></p>
</div>
<p>Now finish putting elements onto the form by inserting the <span class="GUILABEL">Extra Cheese</span> check box and the <span class="GUILABEL">OK</span> and <span class="GUILABEL">Cancel</span> push buttons. Put them roughly where they were in the previous form. Your form should now look like the one in <a href="#QT-DESIGNER-LAYOUTTUTSTEP5">Figure 4-8</a>.</p>
<div class="FIGURE">
<a name="QT-DESIGNER-LAYOUTTUTSTEP5"></a>
<p><b>Figure 4-8. More widgets to be laid out</b></p>
<p><img src="figures/layouttutstep5.png"></p>
</div>
<p>At this point, you could say that we have five different elements on the form: the two button groups, the <span class="GUILABEL">Extra Cheese</span> check box, 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 laid out and done. We just consider them elementary widgets for the time being. But now we want to lay out 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 lay them out 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 laying out. The distinction between the two stages is more a conceptual one than one that is enforced by the program.</p>
<p>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 people's 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 laid out 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 rather rare.</p>
<p>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 <span class="GUILABEL">Extra Cheese</span> check box on a row by itself, and put the two push buttons in a third row. Then, we just put these three rows on top of each other in a vertical layout.</p>
<p>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 assigning 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.</p>
<p>Luckily, we can just select the widgets that we want to be laid out and select a layout manager for them, and Qt Designer will automatically provide an invisible container. In the generated dialog or widget, these invisible containers will be sublayouts. Thus, click on the left button group, hold down the <b class="KEYCAP">Shift</b> key, and click on the second button group so that these two (and nothing else) are selected. Now use any of the means described earlier to assign a horizontal layout manager. The two button groups are aligned, and a thin red frame indicates the invisible container that was created to hold the row layout manager (see <a href="#QT-DESIGNER-FIG-LAYOUTTUTSTEP6">Figure 4-9</a>).</p>
<div class="FIGURE">
<a name="QT-DESIGNER-FIG-LAYOUTTUTSTEP6"></a>
<p><b>Figure 4-9. A new layout manager was created for the button groups</b></p>
<p><img src="figures/layouttutstep6.png"></p>
</div>
<p>Now do the same with the two push buttons. With these steps, the elements to be laid out have been reduced to three: the two laid out rows and the single check box in between. It is not necessary at this point to put the check box in a row all by itself.</p>
<p>Next, select the form 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 <span class="GUILABEL">Extra Cheese</span> check box, 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 <a href="#QT-DESIGNER-FIG-LAYOUTTUTSTEP7">Figure 4-10</a>. Some things might not be perfect (for example, the <span class="GUILABEL">Extra Cheese</span> check box should be centered below the button groups), but we'll fix that later.</p>
<div class="FIGURE">
<a name="QT-DESIGNER-FIG-LAYOUTTUTSTEP7"></a>
<p><b>Figure 4-10. All widgets are arranged</b></p>
<p><img src="figures/layouttutstep7.png"></p>
</div>
<p>To test the correct behavior of the dialog while resizing, go into test mode as described previously and try resizing the dialog. See how the space is distributed among the widgets. Also notice that you cannot make the dialog smaller than the minimum size needed to accommodate all the widgets.</p>
</div>
</div>
<div class="NAVFOOTER">
<br>
<br>
<table width="100%" border="0" cellpadding="3" cellspacing="0" bgcolor="black">
<tr>
<td width="33%" align="left" valign="top"> <a href="chap3_4.html"><img height="20" width="20" src="arrows/left.png" border="0"></a></td>
<td width="34%" align="center" valign="top"> <a href="book1.html"><img height="20" width="25" src="arrows/home.png" border="0"></a></td>
<td width="33%" align="right" valign="top"> <a href="chap4_2.html"><img height="20" width="20" src="arrows/right.png" border="0"></a></td>
</tr>
<tr>
<td width="33%" align="left" valign="top"><font color="white">Connecting Widgets To Each Other</font></td>
<td width="34%" align="center" valign="top"> <a href="part1index.html"><img height="20" width="20" src="arrows/up.png" border="0"></a></td>
<td width="33%" align="right" valign="top"><font color="white">Popular Mechanics: Working With Spacers</font></td>
</tr>
</table>
</div>
</body>
</html>
|