46 \since 4.6 |
46 \since 4.6 |
47 \ingroup appearance |
47 \ingroup appearance |
48 \ingroup geomanagement |
48 \ingroup geomanagement |
49 \ingroup graphicsview-api |
49 \ingroup graphicsview-api |
50 |
50 |
51 The anchor layout is a layout where one can specify how widgets should be placed relative to |
51 The anchor layout allows developers to specify how widgets should be placed relative to |
52 each other. The specification is called an anchor, and it is set up by calling anchor(). |
52 each other, and to the layout itself. The specification is made by adding anchors to the |
|
53 layout by calling addAnchor(), addAnchors() or addCornerAnchors(). |
|
54 |
|
55 Existing anchors in the layout can be accessed with the anchor() function. |
|
56 Items that are anchored are automatically added to the layout, and if items |
|
57 are removed, all their anchors will be automatically removed. |
|
58 |
|
59 \beginfloatleft |
|
60 \inlineimage simpleanchorlayout-example.png Using an anchor layout to align simple colored widgets. |
|
61 \endfloat |
|
62 |
53 Anchors are always set up between edges of an item, where the "center" is also considered to |
63 Anchors are always set up between edges of an item, where the "center" is also considered to |
54 be an edge. Considering this example: |
64 be an edge. Consider the following example: |
55 \code |
65 |
56 QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; |
66 \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding anchors |
57 QGraphicsWidget *a = new QGraphicsWidget; |
67 |
58 QGraphicsWidget *b = new QGraphicsWidget; |
68 Here, the right edge of item \c a is anchored to the left edge of item \c b and the bottom |
59 l->anchor(a, Qt::AnchorRight, b, Qt::AnchorLeft); |
69 edge of item \c a is anchored to the top edge of item \c b, with the result that |
60 \endcode |
70 item \c b will be placed diagonally to the right and below item \c b. |
61 |
71 |
62 Here is the right edge of item A anchored to the left edge of item B, with the result that |
72 The addCornerAnchors() function provides a simpler way of anchoring the corners |
63 item B will be placed to the right of item A, with a spacing between A and B. If the |
73 of two widgets than the two individual calls to addAnchor() shown in the code |
64 spacing is negative, the items will overlap to some extent. Items that are anchored are |
74 above. Here, we see how a widget can be anchored to the top-left corner of the enclosing |
65 automatically added to the layout, and if items are removed, all their anchors will be |
75 layout: |
66 automatically removed |
76 |
67 |
77 \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding a corner anchor |
68 \section1 Size Hints and Size Policies in QGraphicsAnchorLayout |
78 |
69 |
79 In cases where anchors are used to match the widths or heights of widgets, it is |
70 QGraphicsAnchorLayout respects each item's size hints and size policies. However it does |
80 convenient to use the addAnchors() function. As with the other functions for specifying |
71 not respect stretch factors currently. This might change in the future, so please refrain |
81 anchors, it can also be used to anchor a widget to a layout. |
72 from using stretch factors in anchor layout to avoid any future regressions. |
82 |
73 |
83 \clearfloat |
74 \section1 Spacing within QGraphicsAnchorLayout |
84 \section1 Size Hints and Size Policies in an Anchor Layout |
75 |
85 |
76 Between the items, the layout can distribute some space. If the spacing has not been |
86 QGraphicsAnchorLayout respects each item's size hints and size policies. |
77 explicitly specified, the actual amount of space will usually be 0, but if the first edge |
87 Note that there are some properties of QSizePolicy that are \l{Known issues}{not respected}. |
78 is the "opposite" of the second edge (i.e. Right is anchored to Left or vice-versa), the |
88 |
79 size of the anchor will be queried from the style through the pixelMetric |
89 \section1 Spacing within an Anchor Layout |
80 PM_LayoutHorizontalSpacing (or PM_LayoutVerticalSpacing for vertical anchors). |
90 |
|
91 The layout may distribute some space between the items. If the spacing has not been |
|
92 explicitly specified, the actual amount of space will usually be 0. |
|
93 |
|
94 However, if the first edge is the \e opposite of the second edge (e.g., the right edge |
|
95 of the first widget is anchored to the left edge of the second widget), the size of the |
|
96 anchor will be queried from the style through a pixel metric: |
|
97 \l{QStyle::}{PM_LayoutHorizontalSpacing} for horizontal anchors and |
|
98 \l{QStyle::}{PM_LayoutVerticalSpacing} for vertical anchors. |
|
99 |
|
100 If the spacing is negative, the items will overlap to some extent. |
|
101 |
|
102 |
|
103 \section1 Known issues |
|
104 There are some features that QGraphicsAnchorLayout currently does not support. |
|
105 This might change in the future, so avoid using these features if you want to |
|
106 avoid any future regressions in behaviour: |
|
107 \list |
|
108 |
|
109 \o Stretch factors are not respected. |
|
110 |
|
111 \o QSizePolicy::ExpandFlag is not respected. |
|
112 |
|
113 \o Height for width is not respected. |
|
114 |
|
115 \endlist |
|
116 |
|
117 \sa QGraphicsLinearLayout, QGraphicsGridLayout, QGraphicsLayout |
81 */ |
118 */ |
82 |
119 |
83 /*! |
120 /*! |
84 \class QGraphicsAnchor |
121 \class QGraphicsAnchor |
85 \brief The QGraphicsAnchor class represents an anchor between two items in a |
122 \brief The QGraphicsAnchor class represents an anchor between two items in a |
119 |
156 |
120 /*! |
157 /*! |
121 \property QGraphicsAnchor::sizePolicy |
158 \property QGraphicsAnchor::sizePolicy |
122 \brief the size policy for the QGraphicsAnchor. |
159 \brief the size policy for the QGraphicsAnchor. |
123 |
160 |
124 By setting the size policy on an anchor you can configure how the item can resize itself |
161 By setting the size policy on an anchor you can configure how the anchor can resize itself |
125 from its preferred spacing. For instance, if the anchor has the size policy |
162 from its preferred spacing. For instance, if the anchor has the size policy |
126 QSizePolicy::Minimum, the spacing is the minimum size of the anchor. However, its size |
163 QSizePolicy::Minimum, the spacing is the minimum size of the anchor. However, its size |
127 can grow up to the anchors maximum size. If the default size policy is QSizePolicy::Fixed, |
164 can grow up to the anchors maximum size. If the default size policy is QSizePolicy::Fixed, |
128 the anchor can neither grow or shrink, which means that the only size the anchor can have |
165 the anchor can neither grow or shrink, which means that the only size the anchor can have |
129 is the spacing. QSizePolicy::Fixed is the default size policy. |
166 is the spacing. QSizePolicy::Fixed is the default size policy. |
208 Q_ASSERT(d->m_vertexList.isEmpty()); |
245 Q_ASSERT(d->m_vertexList.isEmpty()); |
209 } |
246 } |
210 |
247 |
211 /*! |
248 /*! |
212 Creates an anchor between the edge \a firstEdge of item \a firstItem and the edge \a secondEdge |
249 Creates an anchor between the edge \a firstEdge of item \a firstItem and the edge \a secondEdge |
213 of item \a secondItem. The magnitude of the anchor is picked up from the style. Anchors |
250 of item \a secondItem. The spacing of the anchor is picked up from the style. Anchors |
214 between a layout edge and an item edge will have a size of 0. |
251 between a layout edge and an item edge will have a size of 0. |
215 If there is already an anchor between the edges, the the new anchor will replace the old one. |
252 If there is already an anchor between the edges, the the new anchor will replace the old one. |
216 |
253 |
217 \a firstItem and \a secondItem are automatically added to the layout if they are not part |
254 \a firstItem and \a secondItem are automatically added to the layout if they are not part |
218 of the layout. This means that count() can increase with up to 2. |
255 of the layout. This means that count() can increase by up to 2. |
219 |
256 |
220 The spacing an anchor will get depends on the type of anchor. For instance, anchors from the |
257 The spacing an anchor will get depends on the type of anchor. For instance, anchors from the |
221 Right edge of one item to the Left edge of another (or vice versa) will use the default |
258 Right edge of one item to the Left edge of another (or vice versa) will use the default |
222 horizontal spacing. The same behaviour applies to Bottom to Top anchors, (but they will use |
259 horizontal spacing. The same behaviour applies to Bottom to Top anchors, (but they will use |
223 the default vertical spacing). For all other anchor combinations, the spacing will be 0. |
260 the default vertical spacing). For all other anchor combinations, the spacing will be 0. |
251 Q_D(QGraphicsAnchorLayout); |
288 Q_D(QGraphicsAnchorLayout); |
252 return d->getAnchor(firstItem, firstEdge, secondItem, secondEdge); |
289 return d->getAnchor(firstItem, firstEdge, secondItem, secondEdge); |
253 } |
290 } |
254 |
291 |
255 /*! |
292 /*! |
256 Creates two anchors between \a firstItem and \a secondItem, where one is for the horizontal |
293 Creates two anchors between \a firstItem and \a secondItem specified by the corners, |
257 edge and another one for the vertical edge that the corners \a firstCorner and \a |
294 \a firstCorner and \a secondCorner, where one is for the horizontal edge and another |
258 secondCorner specifies. |
295 one for the vertical edge. |
259 The magnitude of the anchors is picked up from the style. |
296 |
260 |
297 This is a convenience function, since anchoring corners can be expressed as anchoring |
261 This is a convenience function, since anchoring corners can be expressed as anchoring two edges. |
298 two edges. For instance: |
262 For instance, |
299 |
263 \code |
300 \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding a corner anchor in two steps |
264 layout->addAnchor(layout, Qt::AnchorTop, b, Qt::AnchorTop); |
301 |
265 layout->addAnchor(layout, Qt::AnchorLeft, b, Qt::AnchorLeft); |
302 This can also be achieved with the following line of code: |
266 \endcode |
303 |
267 |
304 \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding a corner anchor |
268 has the same effect as |
|
269 |
|
270 \code |
|
271 layout->addCornerAnchors(layout, Qt::TopLeft, b, Qt::TopLeft); |
|
272 \endcode |
|
273 |
305 |
274 If there is already an anchor between the edge pairs, it will be replaced by the anchors that |
306 If there is already an anchor between the edge pairs, it will be replaced by the anchors that |
275 this function specifies. |
307 this function specifies. |
276 |
308 |
277 \a firstItem and \a secondItem are automatically added to the layout if they are not part of the |
309 \a firstItem and \a secondItem are automatically added to the layout if they are not part of the |
278 layout. This means that count() can increase with up to 2. |
310 layout. This means that count() can increase by up to 2. |
|
311 |
|
312 \sa addAnchor(), addAnchors() |
279 */ |
313 */ |
280 void QGraphicsAnchorLayout::addCornerAnchors(QGraphicsLayoutItem *firstItem, |
314 void QGraphicsAnchorLayout::addCornerAnchors(QGraphicsLayoutItem *firstItem, |
281 Qt::Corner firstCorner, |
315 Qt::Corner firstCorner, |
282 QGraphicsLayoutItem *secondItem, |
316 QGraphicsLayoutItem *secondItem, |
283 Qt::Corner secondCorner) |
317 Qt::Corner secondCorner) |
285 Q_D(QGraphicsAnchorLayout); |
319 Q_D(QGraphicsAnchorLayout); |
286 |
320 |
287 // Horizontal anchor |
321 // Horizontal anchor |
288 Qt::AnchorPoint firstEdge = (firstCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft); |
322 Qt::AnchorPoint firstEdge = (firstCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft); |
289 Qt::AnchorPoint secondEdge = (secondCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft); |
323 Qt::AnchorPoint secondEdge = (secondCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft); |
290 d->addAnchor(firstItem, firstEdge, secondItem, secondEdge); |
324 if (d->addAnchor(firstItem, firstEdge, secondItem, secondEdge)) { |
291 |
325 // Vertical anchor |
292 // Vertical anchor |
326 firstEdge = (firstCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop); |
293 firstEdge = (firstCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop); |
327 secondEdge = (secondCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop); |
294 secondEdge = (secondCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop); |
328 d->addAnchor(firstItem, firstEdge, secondItem, secondEdge); |
295 d->addAnchor(firstItem, firstEdge, secondItem, secondEdge); |
329 |
296 |
330 invalidate(); |
297 invalidate(); |
331 } |
298 } |
332 } |
299 |
333 |
300 /*! |
334 /*! |
301 Anchors two or four edges of \a firstItem with the corresponding |
335 Anchors two or four edges of \a firstItem with the corresponding |
302 edges of \a secondItem, so that \a firstItem has the same size as |
336 edges of \a secondItem, so that \a firstItem has the same size as |
303 \a secondItem in the dimensions specified by \a orientations. |
337 \a secondItem in the dimensions specified by \a orientations. |
304 |
338 |
305 Calling this convenience function with the following arguments |
339 For example, the following example anchors the left and right edges of two items |
306 \code |
340 to match their widths: |
307 l->addAnchors(firstItem, secondItem, Qt::Horizontal) |
341 |
308 \endcode |
342 \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding anchors to match sizes in two steps |
309 |
343 |
310 is the same as |
344 This can also be achieved using the following line of code: |
311 |
345 |
312 \code |
346 \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding anchors to match sizes |
313 l->addAnchor(firstItem, Qt::AnchorLeft, secondItem, Qt::AnchorLeft); |
347 |
314 l->addAnchor(firstItem, Qt::AnchorRight, secondItem, Qt::AnchorRight); |
348 \sa addAnchor(), addCornerAnchors() |
315 \endcode |
|
316 */ |
349 */ |
317 void QGraphicsAnchorLayout::addAnchors(QGraphicsLayoutItem *firstItem, |
350 void QGraphicsAnchorLayout::addAnchors(QGraphicsLayoutItem *firstItem, |
318 QGraphicsLayoutItem *secondItem, |
351 QGraphicsLayoutItem *secondItem, |
319 Qt::Orientations orientations) |
352 Qt::Orientations orientations) |
320 { |
353 { |
|
354 bool ok = true; |
321 if (orientations & Qt::Horizontal) { |
355 if (orientations & Qt::Horizontal) { |
322 addAnchor(secondItem, Qt::AnchorLeft, firstItem, Qt::AnchorLeft); |
356 // Currently, if the first is ok, then the rest of the calls should be ok |
323 addAnchor(firstItem, Qt::AnchorRight, secondItem, Qt::AnchorRight); |
357 ok = addAnchor(secondItem, Qt::AnchorLeft, firstItem, Qt::AnchorLeft) != 0; |
|
358 if (ok) |
|
359 addAnchor(firstItem, Qt::AnchorRight, secondItem, Qt::AnchorRight); |
324 } |
360 } |
325 if (orientations & Qt::Vertical) { |
361 if (orientations & Qt::Vertical && ok) { |
326 addAnchor(secondItem, Qt::AnchorTop, firstItem, Qt::AnchorTop); |
362 addAnchor(secondItem, Qt::AnchorTop, firstItem, Qt::AnchorTop); |
327 addAnchor(firstItem, Qt::AnchorBottom, secondItem, Qt::AnchorBottom); |
363 addAnchor(firstItem, Qt::AnchorBottom, secondItem, Qt::AnchorBottom); |
328 } |
364 } |
329 } |
365 } |
330 |
366 |
354 */ |
384 */ |
355 void QGraphicsAnchorLayout::setVerticalSpacing(qreal spacing) |
385 void QGraphicsAnchorLayout::setVerticalSpacing(qreal spacing) |
356 { |
386 { |
357 Q_D(QGraphicsAnchorLayout); |
387 Q_D(QGraphicsAnchorLayout); |
358 |
388 |
359 // ### We don't support negative spacing yet |
|
360 if (spacing < 0) { |
|
361 spacing = 0; |
|
362 qWarning() << "QGraphicsAnchorLayout does not support negative spacing."; |
|
363 } |
|
364 |
|
365 d->spacings[1] = spacing; |
389 d->spacings[1] = spacing; |
366 invalidate(); |
390 invalidate(); |
367 } |
391 } |
368 |
392 |
369 /*! |
393 /*! |
370 Sets the default horizontal and the default vertical spacing for the anchor layout to \a spacing. |
394 Sets the default horizontal and the default vertical spacing for the anchor layout to \a spacing. |
371 |
395 |
372 If an item is anchored with no spacing associated with the anchor, it will use the default |
396 If an item is anchored with no spacing associated with the anchor, it will use the default |
373 spacing. |
397 spacing. |
374 |
398 |
375 Currently QGraphicsAnchorLayout does not support negative default spacings. |
399 QGraphicsAnchorLayout does not support negative spacings. Setting a negative value will unset the |
|
400 previous spacing and make the layout use the spacing provided by the current widget style. |
376 |
401 |
377 \sa setHorizontalSpacing(), setVerticalSpacing() |
402 \sa setHorizontalSpacing(), setVerticalSpacing() |
378 */ |
403 */ |
379 void QGraphicsAnchorLayout::setSpacing(qreal spacing) |
404 void QGraphicsAnchorLayout::setSpacing(qreal spacing) |
380 { |
405 { |
381 Q_D(QGraphicsAnchorLayout); |
406 Q_D(QGraphicsAnchorLayout); |
382 |
|
383 // ### Currently we do not support negative anchors inside the graph. |
|
384 // To avoid those being created by a negative spacing, we must |
|
385 // make this test. |
|
386 if (spacing < 0) { |
|
387 spacing = 0; |
|
388 qWarning() << "QGraphicsAnchorLayout does not support negative spacing."; |
|
389 } |
|
390 |
407 |
391 d->spacings[0] = d->spacings[1] = spacing; |
408 d->spacings[0] = d->spacings[1] = spacing; |
392 invalidate(); |
409 invalidate(); |
393 } |
410 } |
394 |
411 |
398 \sa verticalSpacing(), setHorizontalSpacing() |
415 \sa verticalSpacing(), setHorizontalSpacing() |
399 */ |
416 */ |
400 qreal QGraphicsAnchorLayout::horizontalSpacing() const |
417 qreal QGraphicsAnchorLayout::horizontalSpacing() const |
401 { |
418 { |
402 Q_D(const QGraphicsAnchorLayout); |
419 Q_D(const QGraphicsAnchorLayout); |
403 return d->effectiveSpacing(QGraphicsAnchorLayoutPrivate::Horizontal); |
420 return d->styleInfo().defaultSpacing(Qt::Horizontal); |
404 } |
421 } |
405 |
422 |
406 /*! |
423 /*! |
407 Returns the default vertical spacing for the anchor layout. |
424 Returns the default vertical spacing for the anchor layout. |
408 |
425 |
409 \sa horizontalSpacing(), setVerticalSpacing() |
426 \sa horizontalSpacing(), setVerticalSpacing() |
410 */ |
427 */ |
411 qreal QGraphicsAnchorLayout::verticalSpacing() const |
428 qreal QGraphicsAnchorLayout::verticalSpacing() const |
412 { |
429 { |
413 Q_D(const QGraphicsAnchorLayout); |
430 Q_D(const QGraphicsAnchorLayout); |
414 return d->effectiveSpacing(QGraphicsAnchorLayoutPrivate::Vertical); |
431 return d->styleInfo().defaultSpacing(Qt::Vertical); |
415 } |
432 } |
416 |
433 |
417 /*! |
434 /*! |
418 \reimp |
435 \reimp |
419 */ |
436 */ |