Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
layout.qdoc
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3/*!
4 \page layout.html
5 \title Layout Management
6 \ingroup qt-basic-concepts
7 \ingroup qt-gui-concepts
8 \brief A tour of the standard layout managers and an introduction to custom
9 layouts.
10
11 \previouspage Qt Widgets
12 \nextpage {Styles and Style Aware Widgets}{Styles}
13
14 \ingroup frameworks-technologies
15
16 The Qt layout system provides a simple and powerful way of automatically
17 arranging child widgets within a widget to ensure that they make good use
18 of the available space.
19
20 \section1 Introduction
21
22 Qt includes a set of layout management classes that are used to describe
23 how widgets are laid out in an application's user interface. These layouts
24 automatically position and resize widgets when the amount of space
25 available for them changes, ensuring that they are consistently arranged
26 and that the user interface as a whole remains usable.
27
28 All QWidget subclasses can use layouts to manage their children. The
29 QWidget::setLayout() function applies a layout to a widget. When a layout
30 is set on a widget in this way, it takes charge of the following tasks:
31
32 \list
33 \li Positioning of child widgets
34 \li Sensible default sizes for windows
35 \li Sensible minimum sizes for windows
36 \li Resize handling
37 \li Automatic updates when contents change:
38 \list
39 \li Font size, text or other contents of child widgets
40 \li Hiding or showing a child widget
41 \li Removal of child widgets
42 \endlist
43 \endlist
44
45 \section1 Qt's Layout Classes
46
47 Qt's layout classes were designed for hand-written C++ code, allowing
48 measurements to be specified in pixels for simplicity, so they are easy to
49 understand and use. The code generated for forms created using \QD also
50 uses the layout classes. \QD is useful to use when experimenting with the
51 design of a form since it avoids the compile, link and run cycle usually
52 involved in user interface development.
53
54 \annotatedlist geomanagement
55
56 \section1 Horizontal, Vertical, Grid, and Form Layouts
57
58 The easiest way to give your widgets a good layout is to use the built-in
59 layout managers: QHBoxLayout, QVBoxLayout, QGridLayout, and QFormLayout.
60 These classes inherit from QLayout, which in turn derives from QObject (not
61 QWidget). They take care of geometry management for a set of widgets. To
62 create more complex layouts, you can nest layout managers inside each other.
63
64 \list
65 \li A QHBoxLayout lays out widgets in a horizontal row, from left to
66 right (or right to left for right-to-left languages).
67 \image qhboxlayout-with-5-children.png
68 {Five buttons in horizontal layout}
69
70 \li A QVBoxLayout lays out widgets in a vertical column, from top to
71 bottom.
72 \image qvboxlayout-with-5-children.png
73 {Five buttons in vertical layout}
74
75 \li A QGridLayout lays out widgets in a two-dimensional grid. Widgets
76 can occupy multiple cells.
77 \image qgridlayout-with-5-children.png
78 {Five buttons in grid layout}
79
80 \li A QFormLayout lays out widgets in a 2-column descriptive label-
81 field style.
82 \image qformlayout-with-6-children.png
83 {Three buttons with text fields in form layout}
84 \endlist
85
86
87 \section2 Laying Out Widgets in Code
88
89 The following code creates a QHBoxLayout that manages the geometry of five
90 \l{QPushButton}{QPushButtons}, as shown on the first screenshot above:
91
92 \snippet layouts/layouts.cpp 0
93 \snippet layouts/layouts.cpp 1
94 \snippet layouts/layouts.cpp 2
95 \codeline
96 \snippet layouts/layouts.cpp 3
97 \snippet layouts/layouts.cpp 4
98 \snippet layouts/layouts.cpp 5
99
100 The code for QVBoxLayout is identical, except the line where the layout is
101 created. The code for QGridLayout is a bit different, because we need to
102 specify the row and column position of the child widget:
103
104 \snippet layouts/layouts.cpp 12
105 \snippet layouts/layouts.cpp 13
106 \snippet layouts/layouts.cpp 14
107 \codeline
108 \snippet layouts/layouts.cpp 15
109 \snippet layouts/layouts.cpp 16
110 \snippet layouts/layouts.cpp 17
111
112 The third QPushButton spans 2 columns. This is possible by specifying 2 as
113 the fifth argument to QGridLayout::addWidget().
114
115 QFormLayout will add two widgets on a row, commonly a QLabel and a QLineEdit
116 to create forms. Adding a QLabel and a QLineEdit on the same row will set
117 the QLineEdit as the QLabel's buddy. The following code will use the
118 QFormLayout to place three \l{QPushButton}{QPushButtons} and a corresponding
119 QLineEdit on a row.
120
121 \snippet layouts/layouts.cpp 18
122 \snippet layouts/layouts.cpp 19
123 \snippet layouts/layouts.cpp 20
124 \codeline
125 \snippet layouts/layouts.cpp 21
126 \snippet layouts/layouts.cpp 22
127 \snippet layouts/layouts.cpp 23
128
129
130 \section2 Tips for Using Layouts
131
132 When you use a layout, you do not need to pass a parent when constructing
133 the child widgets. The layout will automatically reparent the widgets
134 (using QWidget::setParent()) so that they are children of the widget on
135 which the layout is installed.
136
137 \note Widgets in a layout are children of the widget on which the layout
138 is installed, \e not of the layout itself. Widgets can only have other
139 widgets as parent, not layouts.
140
141 You can nest layouts using \c addLayout() on a layout; the inner layout
142 then becomes a child of the layout it is inserted into.
143
144
145 \section1 Adding Widgets to a Layout
146
147 When you add widgets to a layout, the layout process works as follows:
148
149 \list 1
150 \li All the widgets will initially be allocated an amount of space in
151 accordance with their QWidget::sizePolicy() and
152 QWidget::sizeHint().
153
154 \li If any of the widgets have stretch factors set, with a value
155 greater than zero, then they are allocated space in proportion to
156 their stretch factor (explained below).
157
158 \li If any of the widgets have stretch factors set to zero they will
159 only get more space if no other widgets want the space. Of these,
160 space is allocated to widgets with an
161 \l{QSizePolicy::Expanding}{Expanding} size policy first.
162
163 \li Any widgets that are allocated less space than their minimum size
164 (or minimum size hint if no minimum size is specified) are
165 allocated this minimum size they require. (Widgets don't have to
166 have a minimum size or minimum size hint in which case the stretch
167 factor is their determining factor.)
168
169 \li Any widgets that are allocated more space than their maximum size
170 are allocated the maximum size space they require. (Widgets do not
171 have to have a maximum size in which case the stretch factor is
172 their determining factor.)
173 \endlist
174
175
176 \section2 Stretch Factors
177 \target stretch factor
178
179 Widgets are normally created without any stretch factor set. When they are
180 laid out in a layout the widgets are given a share of space in accordance
181 with their QWidget::sizePolicy() or their minimum size hint whichever is
182 the greater. Stretch factors are used to change how much space widgets are
183 given in proportion to one another.
184
185 If we have three widgets laid out using a QHBoxLayout with no stretch
186 factors set we will get a layout like this:
187
188 \image layout1.png {Three evenly spaced widgets in a row}
189
190 If we apply stretch factors to each widget, they will be laid out in
191 proportion (but never less than their minimum size hint), e.g.
192
193 \image layout2.png {Three stretched widgets in a row}
194
195
196 \section1 Custom Widgets in Layouts
197
198 When you make your own widget class, you should also communicate its layout
199 properties. If the widget uses one of Qt's layouts, this is already taken
200 care of. If the widget does not have any child widgets, or uses a manual
201 layout, you can change the behavior of the widget using any or all of the
202 following mechanisms:
203
204 \list
205 \li Reimplement QWidget::sizeHint() to return the preferred size of the
206 widget.
207 \li Reimplement QWidget::minimumSizeHint() to return the smallest size
208 the widget can have.
209 \li Call QWidget::setSizePolicy() to specify the space requirements of
210 the widget.
211 \endlist
212
213 Call QWidget::updateGeometry() whenever the size hint, minimum size hint or
214 size policy changes. This will cause a layout recalculation. Multiple
215 consecutive calls to QWidget::updateGeometry() will only cause one layout
216 recalculation.
217
218 If the preferred height of your widget depends on its actual width (e.g.,
219 a label with automatic word-breaking), set the
220 \l{QSizePolicy::hasHeightForWidth()}{height-for-width} flag in the
221 widget's \l{QWidget::sizePolicy}{size policy} and reimplement
222 QWidget::heightForWidth().
223
224 Even if you implement QWidget::heightForWidth(), it is still a good idea to
225 provide a reasonable sizeHint().
226
227 For further guidance when implementing these functions, see the
228 \e{Qt Quarterly} article
229 \l{http://doc.qt.io/archives/qq/qq04-height-for-width.html}
230 {Trading Height for Width}.
231
232
233 \section1 Layout Issues
234
235 The use of rich text in a label widget can introduce some problems to the
236 layout of its parent widget. Problems occur due to the way rich text is
237 handled by Qt's layout managers when the label is word wrapped.
238
239 In certain cases the parent layout is put into QLayout::FreeResize mode,
240 meaning that it will not adapt the layout of its contents to fit inside
241 small sized windows, or even prevent the user from making the window too
242 small to be usable. This can be overcome by subclassing the problematic
243 widgets, and implementing suitable \l{QWidget::}{sizeHint()} and
244 \l{QWidget::}{minimumSizeHint()} functions.
245
246 In some cases, it is relevant when a layout is added to a widget. When
247 you set the widget of a QDockWidget or a QScrollArea (with
248 QDockWidget::setWidget() and QScrollArea::setWidget()), the layout must
249 already have been set on the widget. If not, the widget will not be
250 visible.
251
252
253 \section1 Manual Layout
254
255 If you are making a one-of-a-kind special layout, you can also make a
256 custom widget as described above. Reimplement QWidget::resizeEvent() to
257 calculate the required distribution of sizes and call
258 \l{QWidget::}{setGeometry()} on each child.
259
260 The widget will get an event of type QEvent::LayoutRequest when the
261 layout needs to be recalculated. Reimplement QWidget::event() to handle
262 QEvent::LayoutRequest events.
263
264
265 \section1 How to Write A Custom Layout Manager
266
267 An alternative to manual layout is to write your own layout manager by
268 subclassing QLayout. The
269 \l{layouts/flowlayout}{Flow Layout} example shows how to do this.
270
271 Here we present an example in detail. The \c CardLayout class is inspired
272 by the Java layout manager of the same name. It lays out the items (widgets
273 or nested layouts) on top of each other, each item offset by
274 QLayout::spacing().
275
276 To write your own layout class, you must define the following:
277 \list
278 \li A data structure to store the items handled by the layout. Each
279 item is a \l{QLayoutItem}{QLayoutItem}. We will use a
280 QList in this example.
281 \li \l{QLayout::}{addItem()}, how to add items to the layout.
282 \li \l{QLayout::}{setGeometry()}, how to perform the layout.
283 \li \l{QLayout::}{sizeHint()}, the preferred size of the layout.
284 \li \l{QLayout::}{itemAt()}, how to iterate over the layout.
285 \li \l{QLayout::}{takeAt()}, how to remove items from the layout.
286 \endlist
287
288 In most cases, you will also implement \l{QLayout::}{minimumSize()}.
289
290
291 \section2 The Header File (\c card.h)
292
293 \snippet code/doc_src_layout.cpp 0
294
295
296 \section2 The Implementation File (\c card.cpp)
297
298 \snippet code/doc_src_layout.cpp 1
299
300 First we define \c{count()} to fetch the number of items in the list.
301
302 \snippet code/doc_src_layout.cpp 2
303
304 Then we define two functions that iterate over the layout: \c{itemAt()}
305 and \c{takeAt()}. These functions are used internally by the layout system
306 to handle deletion of widgets. They are also available for application
307 programmers.
308
309 \c{itemAt()} returns the item at the given index. \c{takeAt()} removes the
310 item at the given index, and returns it. In this case we use the list index
311 as the layout index. In other cases where we have a more complex data
312 structure, we may have to spend more effort defining a linear order for the
313 items.
314
315 \snippet code/doc_src_layout.cpp 3
316
317 \c{addItem()} implements the default placement strategy for layout items.
318 This function must be implemented. It is used by QLayout::add(), by the
319 QLayout constructor that takes a layout as parent. If your layout has
320 advanced placement options that require parameters, you must provide extra
321 access functions such as the row and column spanning overloads of
322 QGridLayout::addItem(), QGridLayout::addWidget(), and
323 QGridLayout::addLayout().
324
325 \snippet code/doc_src_layout.cpp 4
326
327 The layout takes over responsibility of the items added. Since QLayoutItem
328 does not inherit QObject, we must delete the items manually. In the
329 destructor, we remove each item from the list using \c{takeAt()}, and
330 then delete it.
331
332 \snippet code/doc_src_layout.cpp 5
333
334 The \c{setGeometry()} function actually performs the layout. The rectangle
335 supplied as an argument does not include \c{margin()}. If relevant, use
336 \c{spacing()} as the distance between items.
337
338 \snippet code/doc_src_layout.cpp 6
339
340 \c{sizeHint()} and \c{minimumSize()} are normally very similar in
341 implementation. The sizes returned by both functions should include
342 \c{spacing()}, but not \c{margin()}.
343
344 \snippet code/doc_src_layout.cpp 7
345
346
347 \section2 Further Notes
348
349 \list
350 \li This custom layout does not handle height for width.
351 \li We ignore QLayoutItem::isEmpty(); this means that the layout will
352 treat hidden widgets as visible.
353 \li For complex layouts, speed can be greatly increased by caching
354 calculated values. In that case, implement
355 QLayoutItem::invalidate() to mark the cached data is dirty.
356 \li Calling QLayoutItem::sizeHint(), etc. may be expensive. So, you
357 should store the value in a local variable if you need it again
358 later within in the same function.
359 \li You should not call QLayoutItem::setGeometry() twice on the same
360 item in the same function. This call can be very expensive if the
361 item has several child widgets, because the layout manager must do
362 a complete layout every time. Instead, calculate the geometry and
363 then set it. (This does not only apply to layouts, you should do
364 the same if you implement your own resizeEvent(), for example.)
365 \endlist
366
367 \section1 Layout Examples
368
369 Many Qt Widgets \l{Qt Widgets Examples}{examples} already use layouts,
370 however, several examples exist to showcase various layouts.
371
372 \annotatedlist examples-layout
373
374*/