1
/****************************************************************************
3
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
7
** This file is part of the documentation of the Qt Toolkit.
9
** $QT_BEGIN_LICENSE:LGPL$
10
** No Commercial Usage
11
** This file contains pre-release code and may not be distributed.
12
** You may use this file in accordance with the terms and conditions
13
** contained in the Technology Preview License Agreement accompanying
16
** GNU Lesser General Public License Usage
17
** Alternatively, this file may be used under the terms of the GNU Lesser
18
** General Public License version 2.1 as published by the Free Software
19
** Foundation and appearing in the file LICENSE.LGPL included in the
20
** packaging of this file. Please review the following information to
21
** ensure the GNU Lesser General Public License version 2.1 requirements
22
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24
** In addition, as a special exception, Nokia gives you certain additional
25
** rights. These rights are described in the Nokia Qt LGPL Exception
26
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28
** If you have questions regarding the use of this file, please contact
29
** Nokia at qt-info@nokia.com.
40
****************************************************************************/
49
\title Layout Management
50
\brief A tour of the standard layout managers and an introduction to custom
53
\previouspage Widget Classes
54
\contentspage Widgets and Layouts
55
\nextpage {Implementing Styles and Style Aware Widgets}{Styles}
57
\ingroup frameworks-technologies
59
The Qt layout system provides a simple and powerful way of automatically
60
arranging child widgets within a widget to ensure that they make good use
61
of the available space.
65
\section1 Introduction
67
Qt includes a set of layout management classes that are used to describe
68
how widgets are laid out in an application's user interface. These layouts
69
automatically position and resize widgets when the amount of space
70
available for them changes, ensuring that they are consistently arranged
71
and that the user interface as a whole remains usable.
73
All QWidget subclasses can use layouts to manage their children. The
74
QWidget::setLayout() function applies a layout to a widget. When a layout
75
is set on a widget in this way, it takes charge of the following tasks:
78
\o Positioning of child widgets.
79
\o Sensible default sizes for windows.
80
\o Sensible minimum sizes for windows.
82
\o Automatic updates when contents change:
84
\o Font size, text or other contents of child widgets.
85
\o Hiding or showing a child widget.
86
\o Removal of child widgets.
90
\section1 Qt's Layout Classes
92
Qt's layout classes were designed for hand-written C++ code, allowing
93
measurements to be specified in pixels for simplicity, so they are easy to
94
understand and use. The code generated for forms created using \QD also
95
uses the layout classes. \QD is useful to use when experimenting with the
96
design of a form since it avoids the compile, link and run cycle usually
97
involved in user interface development.
99
\annotatedlist geomanagement
101
\section1 Horizontal, Vertical, Grid, and Form Layouts
103
The easiest way to give your widgets a good layout is to use the built-in
104
layout managers: QHBoxLayout, QVBoxLayout, QGridLayout, and QFormLayout.
105
These classes inherit from QLayout, which in turn derives from QObject (not
106
QWidget). They take care of geometry management for a set of widgets. To
107
create more complex layouts, you can nest layout managers inside each other.
110
\o A QHBoxLayout lays out widgets in a horizontal row, from left to
111
right (or right to left for right-to-left languages).
112
\image qhboxlayout-with-5-children.png
114
\o A QVBoxLayout lays out widgets in a vertical column, from top to
116
\image qvboxlayout-with-5-children.png
118
\o A QGridLayout lays out widgets in a two-dimensional grid. Widgets
119
can occupy multiple cells.
120
\image qgridlayout-with-5-children.png
122
\o A QFormLayout lays out widgets in a 2-column descriptive label-
124
\image qformlayout-with-6-children.png
128
\section2 Laying Out Widgets in Code
130
The following code creates a QHBoxLayout that manages the geometry of five
131
\l{QPushButton}s, as shown on the first screenshot above:
133
\snippet doc/src/snippets/layouts/layouts.cpp 0
134
\snippet doc/src/snippets/layouts/layouts.cpp 1
135
\snippet doc/src/snippets/layouts/layouts.cpp 2
137
\snippet doc/src/snippets/layouts/layouts.cpp 3
138
\snippet doc/src/snippets/layouts/layouts.cpp 4
139
\snippet doc/src/snippets/layouts/layouts.cpp 5
141
The code for QVBoxLayout is identical, except the line where the layout is
142
created. The code for QGridLayout is a bit different, because we need to
143
specify the row and column position of the child widget:
145
\snippet doc/src/snippets/layouts/layouts.cpp 12
146
\snippet doc/src/snippets/layouts/layouts.cpp 13
147
\snippet doc/src/snippets/layouts/layouts.cpp 14
149
\snippet doc/src/snippets/layouts/layouts.cpp 15
150
\snippet doc/src/snippets/layouts/layouts.cpp 16
151
\snippet doc/src/snippets/layouts/layouts.cpp 17
153
The third QPushButton spans 2 columns. This is possible by specifying 2 as
154
the fifth argument to QGridLayout::addWidget().
156
Finally, the code for QFormLayout is ..
159
\section2 Tips for Using Layouts
161
When you use a layout, you do not need to pass a parent when constructing
162
the child widgets. The layout will automatically reparent the widgets
163
(using QWidget::setParent()) so that they are children of the widget on
164
which the layout is installed.
166
\note Widgets in a layout are children of the widget on which the layout
167
is installed, \e not of the layout itself. Widgets can only have other
168
widgets as parent, not layouts.
170
You can nest layouts using \c addLayout() on a layout; the inner layout
171
then becomes a child of the layout it is inserted into.
174
\section1 Adding Widgets to a Layout
176
When you add widgets to a layout, the layout process works as follows:
179
\o All the widgets will initially be allocated an amount of space in
180
accordance with their QWidget::sizePolicy() and
183
\o If any of the widgets have stretch factors set, with a value
184
greater than zero, then they are allocated space in proportion to
185
their stretch factor (explained below).
187
\o If any of the widgets have stretch factors set to zero they will
188
only get more space if no other widgets want the space. Of these,
189
space is allocated to widgets with an
190
\l{QSizePolicy::Expanding}{Expanding} size policy first.
192
\o Any widgets that are allocated less space than their minimum size
193
(or minimum size hint if no minimum size is specified) are
194
allocated this minimum size they require. (Widgets don't have to
195
have a minimum size or minimum size hint in which case the strech
196
factor is their determining factor.)
198
\o Any widgets that are allocated more space than their maximum size
199
are allocated the maximum size space they require. (Widgets do not
200
have to have a maximum size in which case the strech factor is
201
their determining factor.)
205
\section2 Stretch Factors
206
\keyword stretch factor
208
Widgets are normally created without any stretch factor set. When they are
209
laid out in a layout the widgets are given a share of space in accordance
210
with their QWidget::sizePolicy() or their minimum size hint whichever is
211
the greater. Stretch factors are used to change how much space widgets are
212
given in proportion to one another.
214
If we have three widgets laid out using a QHBoxLayout with no stretch
215
factors set we will get a layout like this:
217
\img layout1.png Three widgets in a row
219
If we apply stretch factors to each widget, they will be laid out in
220
proportion (but never less than their minimum size hint), e.g.
222
\img layout2.png Three widgets with different stretch factors in a row
225
\section1 Custom Widgets in Layouts
227
When you make your own widget class, you should also communicate its layout
228
properties. If the widget has a one of Qt's layouts, this is already taken
229
care of. If the widget does not have any child widgets, or uses manual
230
layout, you can change the behavior of the widget using any or all of the
231
following mechanisms:
234
\o Reimplement QWidget::sizeHint() to return the preferred size of the
236
\o Reimplement QWidget::minimumSizeHint() to return the smallest size
238
\o Call QWidget::setSizePolicy() to specify the space requirements of
242
Call QWidget::updateGeometry() whenever the size hint, minimum size hint or
243
size policy changes. This will cause a layout recalculation. Multiple
244
consecutive calls to QWidget::updateGeometry() will only cause one layout
247
If the preferred height of your widget depends on its actual width (e.g.,
248
a label with automatic word-breaking), set the
249
\l{QSizePolicy::hasHeightForWidth()}{height-for-width} flag in the
250
widget's \l{QWidget::sizePolicy}{size policy} and reimplement
251
QWidget::heightForWidth().
253
Even if you implement QWidget::heightForWidth(), it is still a good idea to
254
provide a reasonable sizeHint().
256
For further guidance when implementing these functions, see the
257
\e{Qt Quarterly} article
258
\l{http://qt.nokia.com/doc/qq/qq04-height-for-width.html}
259
{Trading Height for Width}.
262
\section1 Layout Issues
264
The use of rich text in a label widget can introduce some problems to the
265
layout of its parent widget. Problems occur due to the way rich text is
266
handled by Qt's layout managers when the label is word wrapped.
268
In certain cases the parent layout is put into QLayout::FreeResize mode,
269
meaning that it will not adapt the layout of its contents to fit inside
270
small sized windows, or even prevent the user from making the window too
271
small to be usable. This can be overcome by subclassing the problematic
272
widgets, and implementing suitable \l{QWidget::}{sizeHint()} and
273
\l{QWidget::}{minimumSizeHint()} functions.
275
In some cases, it is relevant when a layout is added to a widget. When
276
you set the widget of a QDockWidget or a QScrollArea (with
277
QDockWidget::setWidget() and QScrollArea::setWidget()), the layout must
278
already have been set on the widget. If not, the widget will not be
282
\section1 Manual Layout
284
If you are making a one-of-a-kind special layout, you can also make a
285
custom widget as described above. Reimplement QWidget::resizeEvent() to
286
calculate the required distribution of sizes and call
287
\l{QWidget::}{setGeometry()} on each child.
289
The widget will get an event of type QEvent::LayoutRequest when the
290
layout needs to be recalculated. Reimplement QWidget::event() to handle
291
QEvent::LayoutRequest events.
294
\section1 How to Write A Custom Layout Manager
296
An alternative to manual layout is to write your own layout manager by
297
subclassing QLayout. The \l{layouts/borderlayout}{Border Layout} and
298
\l{layouts/flowlayout}{Flow Layout} examples show how to do this.
300
Here we present an example in detail. The \c CardLayout class is inspired
301
by the Java layout manager of the same name. It lays out the items (widgets
302
or nested layouts) on top of each other, each item offset by
305
To write your own layout class, you must define the following:
307
\o A data structure to store the items handled by the layout. Each
308
item is a \link QLayoutItem QLayoutItem\endlink. We will use a
309
QList in this example.
310
\o \l{QLayout::}{addItem()}, how to add items to the layout.
311
\o \l{QLayout::}{setGeometry()}, how to perform the layout.
312
\o \l{QLayout::}{sizeHint()}, the preferred size of the layout.
313
\o \l{QLayout::}{itemAt()}, how to iterate over the layout.
314
\o \l{QLayout::}{takeAt()}, how to remove items from the layout.
317
In most cases, you will also implement \l{QLayout::}{minimumSize()}.
320
\section2 The Header File (\c card.h)
322
\snippet doc/src/snippets/code/doc_src_layout.qdoc 0
325
\section2 The Implementation File (\c card.cpp)
327
\snippet doc/src/snippets/code/doc_src_layout.qdoc 1
329
First we define \c{count()} to fetch the number of items in the list.
331
\snippet doc/src/snippets/code/doc_src_layout.qdoc 2
333
Then we define two functions that iterate over the layout: \c{itemAt()}
334
and \c{takeAt()}. These functions are used internally by the layout system
335
to handle deletion of widgets. They are also available for application
338
\c{itemAt()} returns the item at the given index. \c{takeAt()} removes the
339
item at the given index, and returns it. In this case we use the list index
340
as the layout index. In other cases where we have a more complex data
341
structure, we may have to spend more effort defining a linear order for the
344
\snippet doc/src/snippets/code/doc_src_layout.qdoc 3
346
\c{addItem()} implements the default placement strategy for layout items.
347
This function must be implemented. It is used by QLayout::add(), by the
348
QLayout constructor that takes a layout as parent. If your layout has
349
advanced placement options that require parameters, you must provide extra
350
access functions such as the row and column spanning overloads of
351
QGridLayout::addItem(), QGridLayout::addWidget(), and
352
QGridLayout::addLayout().
354
\snippet doc/src/snippets/code/doc_src_layout.qdoc 4
356
The layout takes over responsibility of the items added. Since QLayoutItem
357
does not inherit QObject, we must delete the items manually. In the
358
destructor, we remove each item from the list using \c{takeAt()}, and
361
\snippet doc/src/snippets/code/doc_src_layout.qdoc 5
363
The \c{setGeometry()} function actually performs the layout. The rectangle
364
supplied as an argument does not include \c{margin()}. If relevant, use
365
\c{spacing()} as the distance between items.
367
\snippet doc/src/snippets/code/doc_src_layout.qdoc 6
369
\c{sizeHint()} and \c{minimumSize()} are normally very similar in
370
implementation. The sizes returned by both functions should include
371
\c{spacing()}, but not \c{margin()}.
373
\snippet doc/src/snippets/code/doc_src_layout.qdoc 7
376
\section2 Further Notes
379
\o This custom layout does not handle height for width.
380
\o We ignore QLayoutItem::isEmpty(); this means that the layout will
381
treat hidden widgets as visible.
382
\o For complex layouts, speed can be greatly increased by caching
383
calculated values. In that case, implement
384
QLayoutItem::invalidate() to mark the cached data is dirty.
385
\o Calling QLayoutItem::sizeHint(), etc. may be expensive. So, you
386
should store the value in a local variable if you need it again
387
later within in the same function.
388
\o You should not call QLayoutItem::setGeometry() twice on the same
389
item in the same function. This call can be very expensive if the
390
item has several child widgets, because the layout manager must do
391
a complete layout every time. Instead, calculate the geometry and
392
then set it. (This does not only apply to layouts, you should do
393
the same if you implement your own resizeEvent(), for example.)