Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qgraphicsanchorlayout.cpp
Go to the documentation of this file.
1
// Copyright (C) 2016 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
// Qt-Security score:significant reason:default
4
5
/*!
6
\class QGraphicsAnchorLayout
7
\brief The QGraphicsAnchorLayout class provides a layout where one can anchor widgets
8
together in Graphics View.
9
\since 4.6
10
\ingroup appearance
11
\ingroup geomanagement
12
\ingroup graphicsview-api
13
\inmodule QtWidgets
14
15
The anchor layout allows developers to specify how widgets should be placed relative to
16
each other, and to the layout itself. The specification is made by adding anchors to the
17
layout by calling addAnchor(), addAnchors() or addCornerAnchors().
18
19
Existing anchors in the layout can be accessed with the anchor() function.
20
Items that are anchored are automatically added to the layout, and if items
21
are removed, all their anchors will be automatically removed.
22
23
\div {class="float-left"}
24
\inlineimage simpleanchorlayout-example.png
25
{Three widgets using anchor layout to align to the widget edges}
26
\caption Using an anchor layout to align simple colored widgets.
27
\enddiv
28
29
Anchors are always set up between edges of an item, where the "center" is also considered to
30
be an edge. Consider the following example:
31
32
\snippet graphicsview/simpleanchorlayout/main.cpp adding anchors
33
34
Here, the right edge of item \c a is anchored to the left edge of item \c b and the bottom
35
edge of item \c a is anchored to the top edge of item \c b, with the result that
36
item \c b will be placed diagonally to the right and below item \c b.
37
38
The addCornerAnchors() function provides a simpler way of anchoring the corners
39
of two widgets than the two individual calls to addAnchor() shown in the code
40
above. Here, we see how a widget can be anchored to the top-left corner of the enclosing
41
layout:
42
43
\snippet graphicsview/simpleanchorlayout/main.cpp adding a corner anchor
44
45
In cases where anchors are used to match the widths or heights of widgets, it is
46
convenient to use the addAnchors() function. As with the other functions for specifying
47
anchors, it can also be used to anchor a widget to a layout.
48
49
\section1 Size Hints and Size Policies in an Anchor Layout
50
51
QGraphicsAnchorLayout respects each item's size hints and size policies.
52
Note that there are some properties of QSizePolicy that are \l{Known issues}{not respected}.
53
54
\section1 Spacing within an Anchor Layout
55
56
The layout may distribute some space between the items. If the spacing has not been
57
explicitly specified, the actual amount of space will usually be 0.
58
59
However, if the first edge is the \e opposite of the second edge (e.g., the right edge
60
of the first widget is anchored to the left edge of the second widget), the size of the
61
anchor will be queried from the style through a pixel metric:
62
\l{QStyle::}{PM_LayoutHorizontalSpacing} for horizontal anchors and
63
\l{QStyle::}{PM_LayoutVerticalSpacing} for vertical anchors.
64
65
If the spacing is negative, the items will overlap to some extent.
66
67
68
\section1 Known Issues
69
There are some features that QGraphicsAnchorLayout currently does not support.
70
This might change in the future, so avoid using these features if you want to
71
avoid any future regressions in behaviour:
72
\list
73
74
\li Stretch factors are not respected.
75
76
\li QSizePolicy::ExpandFlag is not respected.
77
78
\li Height for width is not respected.
79
80
\endlist
81
82
\sa QGraphicsLinearLayout, QGraphicsGridLayout, QGraphicsLayout
83
*/
84
85
/*!
86
\class QGraphicsAnchor
87
\brief The QGraphicsAnchor class represents an anchor between two items in a
88
QGraphicsAnchorLayout.
89
\since 4.6
90
\ingroup appearance
91
\ingroup geomanagement
92
\ingroup graphicsview-api
93
\inmodule QtWidgets
94
95
The graphics anchor provides an API that enables you to query and manipulate the
96
properties an anchor has. When an anchor is added to the layout with
97
QGraphicsAnchorLayout::addAnchor(), a QGraphicsAnchor instance is returned where the properties
98
are initialized to their default values. The properties can then be further changed, and they
99
will be picked up the next time the layout is activated.
100
101
\sa QGraphicsAnchorLayout::anchor()
102
103
*/
104
#
include
"qgraphicsanchorlayout_p.h"
105
106
QT_BEGIN_NAMESPACE
107
108
QGraphicsAnchor::QGraphicsAnchor(QGraphicsAnchorLayout *parentLayout)
109
: QObject(*(
new
QGraphicsAnchorPrivate))
110
{
111
Q_D(QGraphicsAnchor);
112
Q_ASSERT(parentLayout);
113
d->layoutPrivate = parentLayout->d_func();
114
}
115
116
/*!
117
Removes the QGraphicsAnchor object from the layout and destroys it.
118
*/
119
QGraphicsAnchor::~QGraphicsAnchor()
120
{
121
}
122
123
/*!
124
\property QGraphicsAnchor::sizePolicy
125
\brief the size policy for the QGraphicsAnchor.
126
127
By setting the size policy on an anchor you can configure how the anchor can resize itself
128
from its preferred spacing. For instance, if the anchor has the size policy
129
QSizePolicy::Minimum, the spacing is the minimum size of the anchor. However, its size
130
can grow up to the anchors maximum size. If the default size policy is QSizePolicy::Fixed,
131
the anchor can neither grow or shrink, which means that the only size the anchor can have
132
is the spacing. QSizePolicy::Fixed is the default size policy.
133
QGraphicsAnchor always has a minimum spacing of 0 and a very large maximum spacing.
134
135
\sa QGraphicsAnchor::spacing
136
*/
137
138
void
QGraphicsAnchor::setSizePolicy(QSizePolicy::Policy policy)
139
{
140
Q_D(QGraphicsAnchor);
141
d->setSizePolicy(policy);
142
}
143
144
QSizePolicy::Policy QGraphicsAnchor::sizePolicy()
const
145
{
146
Q_D(
const
QGraphicsAnchor);
147
return
d->sizePolicy;
148
}
149
150
/*!
151
\property QGraphicsAnchor::spacing
152
\brief the preferred space between items in the QGraphicsAnchorLayout.
153
154
Depending on the anchor type, the default spacing is either
155
0 or a value returned from the style.
156
157
\sa QGraphicsAnchorLayout::addAnchor()
158
*/
159
void
QGraphicsAnchor::setSpacing(qreal spacing)
160
{
161
Q_D(QGraphicsAnchor);
162
d->setSpacing(spacing);
163
}
164
165
qreal QGraphicsAnchor::spacing()
const
166
{
167
Q_D(
const
QGraphicsAnchor);
168
return
d->spacing();
169
}
170
171
void
QGraphicsAnchor::unsetSpacing()
172
{
173
Q_D(QGraphicsAnchor);
174
d->unsetSpacing();
175
}
176
177
/*!
178
Constructs a QGraphicsAnchorLayout instance. \a parent is passed to
179
QGraphicsLayout's constructor.
180
*/
181
QGraphicsAnchorLayout::QGraphicsAnchorLayout(QGraphicsLayoutItem *parent)
182
: QGraphicsLayout(*
new
QGraphicsAnchorLayoutPrivate(), parent)
183
{
184
Q_D(QGraphicsAnchorLayout);
185
d->createLayoutEdges();
186
}
187
188
/*!
189
Destroys the QGraphicsAnchorLayout object.
190
*/
191
QGraphicsAnchorLayout::~QGraphicsAnchorLayout()
192
{
193
Q_D(QGraphicsAnchorLayout);
194
195
for
(
int
i = count() - 1; i >= 0; --i) {
196
QGraphicsLayoutItem *item = d->items.at(i);
197
removeAt(i);
198
if
(item) {
199
if
(item->ownedByLayout())
200
delete
item;
201
}
202
}
203
204
d->removeCenterConstraints(
this
, Qt::Horizontal);
205
d->removeCenterConstraints(
this
, Qt::Vertical);
206
d->deleteLayoutEdges();
207
208
Q_ASSERT(d->itemCenterConstraints[Qt::Horizontal].isEmpty());
209
Q_ASSERT(d->itemCenterConstraints[Qt::Vertical].isEmpty());
210
Q_ASSERT(d->items.isEmpty());
211
Q_ASSERT(d->m_vertexList.isEmpty());
212
}
213
214
/*!
215
Creates an anchor between the edge \a firstEdge of item \a firstItem and the edge \a secondEdge
216
of item \a secondItem. The spacing of the anchor is picked up from the style. Anchors
217
between a layout edge and an item edge will have a size of 0.
218
If there is already an anchor between the edges, the new anchor will replace the old one.
219
220
\a firstItem and \a secondItem are automatically added to the layout if they are not part
221
of the layout. This means that count() can increase by up to 2.
222
223
The spacing an anchor will get depends on the type of anchor. For instance, anchors from the
224
Right edge of one item to the Left edge of another (or vice versa) will use the default
225
horizontal spacing. The same behaviour applies to Bottom to Top anchors, (but they will use
226
the default vertical spacing). For all other anchor combinations, the spacing will be 0.
227
All anchoring functions will follow this rule.
228
229
The spacing can also be set manually by using QGraphicsAnchor::setSpacing() method.
230
231
Calling this function where \a firstItem or \a secondItem are ancestors of the layout have
232
undefined behaviour.
233
234
\sa addAnchors(), addCornerAnchors()
235
*/
236
QGraphicsAnchor *
237
QGraphicsAnchorLayout::addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge,
238
QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge)
239
{
240
Q_D(QGraphicsAnchorLayout);
241
QGraphicsAnchor *a = d->addAnchor(firstItem, firstEdge, secondItem, secondEdge);
242
invalidate();
243
return
a;
244
}
245
246
/*!
247
Returns the anchor between the anchor points defined by \a firstItem and \a firstEdge and
248
\a secondItem and \a secondEdge. If there is no such anchor, the function will return 0.
249
*/
250
QGraphicsAnchor *
251
QGraphicsAnchorLayout::anchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge,
252
QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge)
253
{
254
Q_D(QGraphicsAnchorLayout);
255
return
d->getAnchor(firstItem, firstEdge, secondItem, secondEdge);
256
}
257
258
/*!
259
Creates two anchors between \a firstItem and \a secondItem specified by the corners,
260
\a firstCorner and \a secondCorner, where one is for the horizontal edge and another
261
one for the vertical edge.
262
263
This is a convenience function, since anchoring corners can be expressed as anchoring
264
two edges. For instance:
265
266
\snippet graphicsview/simpleanchorlayout/main.cpp adding a corner anchor in two steps
267
268
This can also be achieved with the following line of code:
269
270
\snippet graphicsview/simpleanchorlayout/main.cpp adding a corner anchor
271
272
If there is already an anchor between the edge pairs, it will be replaced by the anchors that
273
this function specifies.
274
275
\a firstItem and \a secondItem are automatically added to the layout if they are not part of the
276
layout. This means that count() can increase by up to 2.
277
278
\sa addAnchor(), addAnchors()
279
*/
280
void
QGraphicsAnchorLayout::addCornerAnchors(QGraphicsLayoutItem *firstItem,
281
Qt::Corner firstCorner,
282
QGraphicsLayoutItem *secondItem,
283
Qt::Corner secondCorner)
284
{
285
Q_D(QGraphicsAnchorLayout);
286
287
// Horizontal anchor
288
Qt::AnchorPoint firstEdge = (firstCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft);
289
Qt::AnchorPoint secondEdge = (secondCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft);
290
if
(d->addAnchor(firstItem, firstEdge, secondItem, secondEdge)) {
291
// Vertical anchor
292
firstEdge = (firstCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop);
293
secondEdge = (secondCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop);
294
d->addAnchor(firstItem, firstEdge, secondItem, secondEdge);
295
296
invalidate();
297
}
298
}
299
300
/*!
301
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
303
\a secondItem in the dimensions specified by \a orientations.
304
305
For example, the following example anchors the left and right edges of two items
306
to match their widths:
307
308
\snippet graphicsview/simpleanchorlayout/main.cpp adding anchors to match sizes in two steps
309
310
This can also be achieved using the following line of code:
311
312
\snippet graphicsview/simpleanchorlayout/main.cpp adding anchors to match sizes
313
314
\sa addAnchor(), addCornerAnchors()
315
*/
316
void
QGraphicsAnchorLayout::addAnchors(QGraphicsLayoutItem *firstItem,
317
QGraphicsLayoutItem *secondItem,
318
Qt::Orientations orientations)
319
{
320
bool
ok =
true
;
321
if
(orientations & Qt::Horizontal) {
322
// Currently, if the first is ok, then the rest of the calls should be ok
323
ok = addAnchor(secondItem, Qt::AnchorLeft, firstItem, Qt::AnchorLeft) !=
nullptr
;
324
if
(ok)
325
addAnchor(firstItem, Qt::AnchorRight, secondItem, Qt::AnchorRight);
326
}
327
if
(orientations & Qt::Vertical && ok) {
328
addAnchor(secondItem, Qt::AnchorTop, firstItem, Qt::AnchorTop);
329
addAnchor(firstItem, Qt::AnchorBottom, secondItem, Qt::AnchorBottom);
330
}
331
}
332
333
/*!
334
Sets the default horizontal spacing for the anchor layout to \a spacing.
335
336
\sa horizontalSpacing(), setVerticalSpacing(), setSpacing()
337
*/
338
void
QGraphicsAnchorLayout::setHorizontalSpacing(qreal spacing)
339
{
340
Q_D(QGraphicsAnchorLayout);
341
342
d->spacings[Qt::Horizontal] = spacing;
343
invalidate();
344
}
345
346
/*!
347
Sets the default vertical spacing for the anchor layout to \a spacing.
348
349
\sa verticalSpacing(), setHorizontalSpacing(), setSpacing()
350
*/
351
void
QGraphicsAnchorLayout::setVerticalSpacing(qreal spacing)
352
{
353
Q_D(QGraphicsAnchorLayout);
354
355
d->spacings[Qt::Vertical] = spacing;
356
invalidate();
357
}
358
359
/*!
360
Sets the default horizontal and the default vertical spacing for the anchor layout to \a spacing.
361
362
If an item is anchored with no spacing associated with the anchor, it will use the default
363
spacing.
364
365
QGraphicsAnchorLayout does not support negative spacings. Setting a negative value will unset the
366
previous spacing and make the layout use the spacing provided by the current widget style.
367
368
\sa setHorizontalSpacing(), setVerticalSpacing()
369
*/
370
void
QGraphicsAnchorLayout::setSpacing(qreal spacing)
371
{
372
Q_D(QGraphicsAnchorLayout);
373
374
d->spacings = {spacing, spacing};
375
invalidate();
376
}
377
378
/*!
379
Returns the default horizontal spacing for the anchor layout.
380
381
\sa verticalSpacing(), setHorizontalSpacing()
382
*/
383
qreal QGraphicsAnchorLayout::horizontalSpacing()
const
384
{
385
Q_D(
const
QGraphicsAnchorLayout);
386
return
d->styleInfo().defaultSpacing(Qt::Horizontal);
387
}
388
389
/*!
390
Returns the default vertical spacing for the anchor layout.
391
392
\sa horizontalSpacing(), setVerticalSpacing()
393
*/
394
qreal QGraphicsAnchorLayout::verticalSpacing()
const
395
{
396
Q_D(
const
QGraphicsAnchorLayout);
397
return
d->styleInfo().defaultSpacing(Qt::Vertical);
398
}
399
400
/*!
401
\reimp
402
*/
403
void
QGraphicsAnchorLayout::setGeometry(
const
QRectF &geom)
404
{
405
Q_D(QGraphicsAnchorLayout);
406
407
QGraphicsLayout::setGeometry(geom);
408
d->calculateVertexPositions(Qt::Horizontal);
409
d->calculateVertexPositions(Qt::Vertical);
410
d->setItemsGeometries(geom);
411
}
412
413
/*!
414
Removes the layout item at \a index without destroying it. Ownership of
415
the item is transferred to the caller.
416
417
Removing an item will also remove any of the anchors associated with it.
418
419
\sa itemAt(), count()
420
*/
421
void
QGraphicsAnchorLayout::removeAt(
int
index)
422
{
423
Q_D(QGraphicsAnchorLayout);
424
QGraphicsLayoutItem *item = d->items.value(index);
425
426
if
(!item)
427
return
;
428
429
// Removing an item affects both horizontal and vertical graphs
430
d->removeCenterConstraints(item, Qt::Horizontal);
431
d->removeCenterConstraints(item, Qt::Vertical);
432
d->removeAnchors(item);
433
d->items.remove(index);
434
435
item->setParentLayoutItem(
nullptr
);
436
invalidate();
437
}
438
439
/*!
440
\reimp
441
*/
442
int
QGraphicsAnchorLayout::count()
const
443
{
444
Q_D(
const
QGraphicsAnchorLayout);
445
return
d->items.size();
446
}
447
448
/*!
449
\reimp
450
*/
451
QGraphicsLayoutItem *QGraphicsAnchorLayout::itemAt(
int
index)
const
452
{
453
Q_D(
const
QGraphicsAnchorLayout);
454
return
d->items.value(index);
455
}
456
457
/*!
458
\reimp
459
*/
460
void
QGraphicsAnchorLayout::invalidate()
461
{
462
Q_D(QGraphicsAnchorLayout);
463
QGraphicsLayout::invalidate();
464
d->calculateGraphCacheDirty =
true
;
465
d->styleInfoDirty =
true
;
466
}
467
468
/*!
469
\reimp
470
*/
471
QSizeF QGraphicsAnchorLayout::sizeHint(Qt::SizeHint which,
const
QSizeF &constraint)
const
472
{
473
Q_UNUSED(constraint);
474
Q_D(
const
QGraphicsAnchorLayout);
475
476
// Some setup calculations are delayed until the information is
477
// actually needed, avoiding unnecessary recalculations when
478
// adding multiple anchors.
479
480
// sizeHint() / effectiveSizeHint() already have a cache
481
// mechanism, using invalidate() to force recalculation. However
482
// sizeHint() is called three times after invalidation (for max,
483
// min and pref), but we just need do our setup once.
484
485
const_cast
<QGraphicsAnchorLayoutPrivate *>(d)->calculateGraphs();
486
487
// ### apply constraint!
488
QSizeF engineSizeHint{d->sizeHints[Qt::Horizontal][which],
489
d->sizeHints[Qt::Vertical][which]};
490
491
qreal left, top, right, bottom;
492
getContentsMargins(&left, &top, &right, &bottom);
493
494
return
engineSizeHint + QSizeF(left + right, top + bottom);
495
}
496
497
QT_END_NAMESPACE
498
499
#
include
"moc_qgraphicsanchorlayout.cpp"
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
qtbase
src
widgets
graphicsview
qgraphicsanchorlayout.cpp
Generated on
for Qt by
1.18.0