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
qquickrectangle.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
6
7#include <QtQml/qqmlinfo.h>
8
9#include <QtQuick/private/qsgcontext_p.h>
10#include <private/qsgadaptationlayer_p.h>
11
12#include <private/qqmlmetatype_p.h>
13
14#include <QtGui/qpixmapcache.h>
15#include <QtCore/qmath.h>
16#include <QtCore/qmetaobject.h>
17
19
20// XXX todo - should we change rectangle to draw entirely within its width/height?
21/*!
22 \internal
23 \class QQuickPen
24 \brief For specifying a pen used for drawing rectangle borders on a QQuickView
25
26 By default, the pen is invalid and nothing is drawn. You must either set a color (then the default
27 width is 1) or a width (then the default color is black).
28
29 A width of 1 indicates is a single-pixel line on the border of the item being painted.
30
31 Example:
32 \qml
33 Rectangle {
34 border.width: 2
35 border.color: "red"
36 }
37 \endqml
38*/
39
40QQuickPen::QQuickPen(QObject *parent)
41 : QObject(parent)
42 , m_width(1)
43 , m_color(Qt::black)
44 , m_aligned(true)
45 , m_valid(false)
46{
47}
48
49qreal QQuickPen::width() const
50{
51 return m_width;
52}
53
54void QQuickPen::setWidth(qreal w)
55{
56 if (m_width == w && m_valid)
57 return;
58
59 m_width = w;
60 m_valid = m_color.alpha() && (qRound(m_width) >= 1 || (!m_aligned && m_width > 0));
61 static_cast<QQuickItem*>(parent())->update();
62 emit widthChanged();
63}
64
65QColor QQuickPen::color() const
66{
67 return m_color;
68}
69
70void QQuickPen::setColor(const QColor &c)
71{
72 m_color = c;
73 m_valid = m_color.alpha() && (qRound(m_width) >= 1 || (!m_aligned && m_width > 0));
74 static_cast<QQuickItem*>(parent())->update();
75 emit colorChanged();
76}
77
78bool QQuickPen::pixelAligned() const
79{
80 return m_aligned;
81}
82
83void QQuickPen::setPixelAligned(bool aligned)
84{
85 if (aligned == m_aligned)
86 return;
87 m_aligned = aligned;
88 m_valid = m_color.alpha() && (qRound(m_width) >= 1 || (!m_aligned && m_width > 0));
89 static_cast<QQuickItem*>(parent())->update();
90 emit pixelAlignedChanged();
91}
92
93bool QQuickPen::isValid() const
94{
95 return m_valid;
96}
97
98/*!
99 \qmltype GradientStop
100 \nativetype QQuickGradientStop
101 \inqmlmodule QtQuick
102 \ingroup qtquick-visual-utility
103 \brief Defines the color at a position in a Gradient.
104
105 \sa Gradient
106*/
107
108/*!
109 \qmlproperty real QtQuick::GradientStop::position
110 \qmlproperty color QtQuick::GradientStop::color
111
112 The position and color properties describe the color used at a given
113 position in a gradient, as represented by a gradient stop.
114
115 The default position is 0.0; the default color is black.
116
117 \sa Gradient
118*/
119QQuickGradientStop::QQuickGradientStop(QObject *parent)
120 : QObject(parent)
121{
122}
123
124qreal QQuickGradientStop::position() const
125{
126 return m_position;
127}
128
129void QQuickGradientStop::setPosition(qreal position)
130{
131 m_position = position; updateGradient();
132}
133
134QColor QQuickGradientStop::color() const
135{
136 return m_color;
137}
138
139void QQuickGradientStop::setColor(const QColor &color)
140{
141 m_color = color; updateGradient();
142}
143
144void QQuickGradientStop::updateGradient()
145{
146 if (QQuickGradient *grad = qobject_cast<QQuickGradient*>(parent()))
147 grad->doUpdate();
148}
149
150/*!
151 \qmltype Gradient
152 \nativetype QQuickGradient
153 \inqmlmodule QtQuick
154 \ingroup qtquick-visual-utility
155 \brief Defines a gradient fill.
156
157 A gradient is defined by two or more colors, which will be blended seamlessly.
158
159 The colors are specified as a set of GradientStop child items, each of
160 which defines a position on the gradient from 0.0 to 1.0 and a color.
161 The position of each GradientStop is defined by setting its
162 \l{GradientStop::}{position} property; its color is defined using its
163 \l{GradientStop::}{color} property.
164
165 A gradient without any gradient stops is rendered as a solid white fill.
166
167 Note that this item is not a visual representation of a gradient. To display a
168 gradient, use a visual item (like \l Rectangle) which supports the use
169 of gradients.
170
171 \section1 Example Usage
172
173 \div {class="float-right"}
174 \inlineimage qml-gradient.png
175 \enddiv
176
177 The following example declares a \l Rectangle item with a gradient starting
178 with red, blending to yellow at one third of the height of the rectangle,
179 and ending with green:
180
181 \snippet qml/gradient.qml code
182
183 \clearfloat
184 \section1 Performance and Limitations
185
186 Calculating gradients can be computationally expensive compared to the use
187 of solid color fills or images. Consider using gradients for static items
188 in a user interface.
189
190 Since Qt 5.12, vertical and horizontal linear gradients can be applied to items.
191 If you need to apply angled gradients, a combination of rotation and clipping
192 can be applied to the relevant items. Alternatively, consider using
193 QtQuick.Shapes::LinearGradient or QtGraphicalEffects::LinearGradient. These
194 approaches can all introduce additional performance requirements for your application.
195
196 The use of animations involving gradient stops may not give the desired
197 result. An alternative way to animate gradients is to use pre-generated
198 images or SVG drawings containing gradients.
199
200 \sa GradientStop
201*/
202
203/*!
204 \qmlproperty list<GradientStop> QtQuick::Gradient::stops
205 \qmldefault
206
207 This property holds the gradient stops describing the gradient.
208
209 By default, this property contains an empty list.
210
211 To set the gradient stops, define them as children of the Gradient.
212*/
213QQuickGradient::QQuickGradient(QObject *parent)
214: QObject(parent)
215{
216}
217
218QQuickGradient::~QQuickGradient()
219{
220}
221
222QQmlListProperty<QQuickGradientStop> QQuickGradient::stops()
223{
224 return QQmlListProperty<QQuickGradientStop>(this, &m_stops);
225}
226
227/*!
228 \qmlproperty enumeration QtQuick::Gradient::orientation
229 \since 5.12
230
231 Set this property to define the direction of the gradient.
232
233 \value Gradient.Vertical a vertical gradient
234 \value Gradient.Horizontal a horizontal gradient
235
236 The default is Gradient.Vertical.
237*/
238void QQuickGradient::setOrientation(Orientation orientation)
239{
240 if (m_orientation == orientation)
241 return;
242
243 m_orientation = orientation;
244 emit orientationChanged();
245 emit updated();
246}
247
248QGradientStops QQuickGradient::gradientStops() const
249{
250 QGradientStops stops;
251 for (int i = 0; i < m_stops.size(); ++i){
252 int j = 0;
253 while (j < stops.size() && stops.at(j).first < m_stops[i]->position())
254 j++;
255 stops.insert(j, QGradientStop(m_stops.at(i)->position(), m_stops.at(i)->color()));
256 }
257 return stops;
258}
259
260void QQuickGradient::doUpdate()
261{
262 emit updated();
263}
264
266
268{
269 bool implicitAA = (radius > 0);
270 if (extraRectangle.isAllocated() && !implicitAA) {
271 const auto &extra = extraRectangle.value();
272 implicitAA = (extra.isTopLeftRadiusSet && extra.topLeftRadius > 0)
273 || (extra.isTopRightRadiusSet && extra.topRightRadius > 0)
274 || (extra.isBottomLeftRadiusSet && extra.bottomLeftRadius > 0)
275 || (extra.isBottomRightRadiusSet && extra.bottomRightRadius > 0);
276 }
277 setImplicitAntialiasing(implicitAA);
278}
279/*!
280 \qmltype Rectangle
281 \nativetype QQuickRectangle
282 \inqmlmodule QtQuick
283 \inherits Item
284 \ingroup qtquick-visual
285 \brief Paints a filled rectangle with an optional border.
286
287 Rectangle items are used to fill areas with solid color or gradients, and/or
288 to provide a rectangular border.
289
290 \section1 Appearance
291
292 Each Rectangle item is painted using either a solid fill color, specified using
293 the \l color property, or a gradient, defined using a Gradient type and set
294 using the \l gradient property. If both a color and a gradient are specified,
295 the gradient is used.
296
297 You can add an optional border to a rectangle with its own color and thickness
298 by setting the \l border.color and \l border.width properties. Set the color
299 to "transparent" to paint a border without a fill color.
300
301 You can also create rounded rectangles using the \l radius property. Since this
302 introduces curved edges to the corners of a rectangle, it may be appropriate to
303 set the \l Item::antialiasing property to improve its appearance. To set the
304 radii individually for different corners, you can use the properties
305 \l topLeftRadius, \l topRightRadius, \l bottomLeftRadius and
306 \l bottomRightRadius.
307
308 \section1 Example Usage
309
310 \div {class="float-right"}
311 \inlineimage declarative-rect.png
312 \enddiv
313
314 The following example shows the effects of some of the common properties on a
315 Rectangle item, which in this case is used to create a square:
316
317 \snippet qml/rectangle/rectangle.qml document
318
319 \clearfloat
320 \section1 Performance
321
322 Using the \l Item::antialiasing property improves the appearance of a rounded rectangle at
323 the cost of rendering performance. You should consider unsetting this property
324 for rectangles in motion, and only set it when they are stationary.
325
326 \sa Image
327*/
328
329QQuickRectangle::QQuickRectangle(QQuickItem *parent)
330: QQuickItem(*(new QQuickRectanglePrivate), parent)
331{
332 setFlag(ItemHasContents);
333#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
334 setAcceptTouchEvents(false);
335#endif
336}
337
338void QQuickRectangle::doUpdate()
339{
340 update();
341}
342
343/*!
344 \qmlproperty bool QtQuick::Rectangle::antialiasing
345
346 Used to decide if the Rectangle should use antialiasing or not.
347 \l {Antialiasing} provides information on the performance implications
348 of this property.
349
350 The default is true for Rectangles with a radius, and false otherwise.
351*/
352
353/*!
354 \qmlpropertygroup QtQuick::Rectangle::border
355 \qmlproperty int QtQuick::Rectangle::border.width
356 \qmlproperty color QtQuick::Rectangle::border.color
357 \qmlproperty bool QtQuick::Rectangle::border.pixelAligned
358
359 The width and color used to draw the border of the rectangle.
360
361 A width of 1 creates a thin line. For no line, use a width of 0 or a transparent color.
362
363 \note The width of the rectangle's border does not affect the geometry of the
364 rectangle itself or its position relative to other items if anchors are used.
365
366 The border is rendered within the rectangle's boundaries.
367
368 If \c pixelAligned is \c true (the default), the rendered border width is rounded to a whole
369 number of pixels, after device pixel ratio scaling. Setting \c pixelAligned to \c false will
370 allow fractional border widths, which may be desirable when \c antialiasing is enabled.
371*/
372QQuickPen *QQuickRectangle::border()
373{
374 Q_D(QQuickRectangle);
375 if (!d->pen) {
376 d->pen = new QQuickPen;
377 QQml_setParent_noEvent(d->pen, this);
378 }
379 return d->pen;
380}
381
382/*!
383 \qmlproperty var QtQuick::Rectangle::gradient
384
385 The gradient to use to fill the rectangle.
386
387 This property allows for the construction of simple vertical or horizontal gradients.
388 Other gradients may be formed by adding rotation to the rectangle.
389
390 \div {class="float-left"}
391 \inlineimage declarative-rect_gradient.png
392 \enddiv
393
394 \snippet qml/rectangle/rectangle-gradient.qml rectangles
395 \clearfloat
396
397 The property also accepts gradient presets from QGradient::Preset. Note however
398 that due to Rectangle only supporting simple vertical or horizontal gradients,
399 any preset with an unsupported angle will revert to the closest representation.
400
401 \snippet qml/rectangle/rectangle-gradient.qml presets
402 \clearfloat
403
404 If both a gradient and a color are specified, the gradient will be used.
405
406 \sa Gradient, color
407*/
408QJSValue QQuickRectangle::gradient() const
409{
410 Q_D(const QQuickRectangle);
411 return d->gradient;
412}
413
414void QQuickRectangle::setGradient(const QJSValue &gradient)
415{
416 Q_D(QQuickRectangle);
417 if (d->gradient.equals(gradient))
418 return;
419
420 static int updatedSignalIdx = QMetaMethod::fromSignal(&QQuickGradient::updated).methodIndex();
421 if (d->doUpdateSlotIdx < 0)
422 d->doUpdateSlotIdx = QQuickRectangle::staticMetaObject.indexOfSlot("doUpdate()");
423
424 if (auto oldGradient = qobject_cast<QQuickGradient*>(d->gradient.toQObject()))
425 QMetaObject::disconnect(oldGradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
426
427 if (gradient.isQObject()) {
428 if (auto newGradient = qobject_cast<QQuickGradient*>(gradient.toQObject())) {
429 d->gradient = gradient;
430 QMetaObject::connect(newGradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
431 } else {
432 qmlWarning(this) << "Can't assign "
433 << QQmlMetaType::prettyTypeName(gradient.toQObject()) << " to gradient property";
434 d->gradient = QJSValue();
435 }
436 } else if (gradient.isNumber() || gradient.isString()) {
437 static const QMetaEnum gradientPresetMetaEnum = QMetaEnum::fromType<QGradient::Preset>();
438 Q_ASSERT(gradientPresetMetaEnum.isValid());
439
440 QGradient result;
441
442 // This code could simply use gradient.toVariant().convert<QGradient::Preset>(),
443 // but QTBUG-76377 prevents us from doing error checks. So we need to
444 // do them manually. Also, NumPresets cannot be used.
445
446 if (gradient.isNumber()) {
447 const auto preset = QGradient::Preset(gradient.toInt());
448 if (preset != QGradient::NumPresets && gradientPresetMetaEnum.valueToKey(preset))
449 result = QGradient(preset);
450 } else if (gradient.isString()) {
451 const auto presetName = gradient.toString();
452 if (presetName != QLatin1String("NumPresets")) {
453 bool ok;
454 const auto presetInt = gradientPresetMetaEnum.keyToValue(qPrintable(presetName), &ok);
455 if (ok)
456 result = QGradient(QGradient::Preset(presetInt));
457 }
458 }
459
460 if (result.type() != QGradient::NoGradient) {
461 d->gradient = gradient;
462 } else {
463 qmlWarning(this) << "No such gradient preset '" << gradient.toString() << "'";
464 d->gradient = QJSValue();
465 }
466 } else if (gradient.isNull() || gradient.isUndefined()) {
467 d->gradient = gradient;
468 } else {
469 qmlWarning(this) << "Unknown gradient type. Expected int, string, or Gradient";
470 d->gradient = QJSValue();
471 }
472
473 update();
474}
475
476void QQuickRectangle::resetGradient()
477{
478 setGradient(QJSValue());
479}
480
481/*!
482 \qmlproperty real QtQuick::Rectangle::radius
483 This property holds the corner radius used to draw a rounded rectangle.
484
485 If radius is non-zero, the rectangle will be painted as a rounded rectangle,
486 otherwise it will be painted as a normal rectangle. Individual corner radii
487 can be set as well (see below). These values will override \l radius. If
488 they are unset (by setting them to \c undefined), \l radius will be used instead.
489
490 \sa topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius
491*/
492qreal QQuickRectangle::radius() const
493{
494 Q_D(const QQuickRectangle);
495 return d->radius;
496}
497
498void QQuickRectangle::setRadius(qreal radius)
499{
500 Q_D(QQuickRectangle);
501 if (d->radius == radius)
502 return;
503
504 d->radius = radius;
505 d->maybeSetImplicitAntialiasing();
506
507 update();
508 emit radiusChanged();
509
510 if (d->extraRectangle.isAllocated()) {
511 if (!d->extraRectangle->isTopLeftRadiusSet)
512 emit topLeftRadiusChanged();
513 if (!d->extraRectangle->isTopRightRadiusSet)
514 emit topRightRadiusChanged();
515 if (!d->extraRectangle->isBottomLeftRadiusSet)
516 emit bottomLeftRadiusChanged();
517 if (!d->extraRectangle->isBottomRightRadiusSet)
518 emit bottomRightRadiusChanged();
519 } else {
520 emit topLeftRadiusChanged();
521 emit topRightRadiusChanged();
522 emit bottomLeftRadiusChanged();
523 emit bottomRightRadiusChanged();
524 }
525}
526
527/*!
528 \since 6.7
529 \qmlproperty real QtQuick::Rectangle::topLeftRadius
530 This property holds the radius used to draw the top left corner.
531
532 If \l topLeftRadius is not set, \l radius will be used instead.
533 If \l topLeftRadius is zero, the corner will be sharp.
534
535 \note This API is considered tech preview and may change or be removed in
536 future versions of Qt.
537
538 \sa radius, topRightRadius, bottomLeftRadius, bottomRightRadius
539*/
540qreal QQuickRectangle::topLeftRadius() const
541{
542 Q_D(const QQuickRectangle);
543 if (d->extraRectangle.isAllocated() && d->extraRectangle->isTopLeftRadiusSet)
544 return d->extraRectangle->topLeftRadius;
545 return d->radius;
546}
547
548void QQuickRectangle::setTopLeftRadius(qreal radius)
549{
550 Q_D(QQuickRectangle);
551 if (d->extraRectangle.isAllocated()
552 && d->extraRectangle->topLeftRadius == radius
553 && d->extraRectangle->isTopLeftRadiusSet) {
554 return;
555 }
556
557 d->extraRectangle.value().topLeftRadius = radius;
558 d->extraRectangle.value().isTopLeftRadiusSet = true;
559 d->maybeSetImplicitAntialiasing();
560
561 update();
562 emit topLeftRadiusChanged();
563}
564
565void QQuickRectangle::resetTopLeftRadius()
566{
567 Q_D(QQuickRectangle);
568 if (!d->extraRectangle.isAllocated())
569 return;
570 if (!d->extraRectangle->isTopLeftRadiusSet)
571 return;
572
573 d->extraRectangle->isTopLeftRadiusSet = false;
574 d->maybeSetImplicitAntialiasing();
575
576 update();
577 emit topLeftRadiusChanged();
578}
579
580/*!
581 \since 6.7
582 \qmlproperty real QtQuick::Rectangle::topRightRadius
583 This property holds the radius used to draw the top right corner.
584
585 If \l topRightRadius is not set, \l radius will be used instead.
586 If \l topRightRadius is zero, the corner will be sharp.
587
588 \note This API is considered tech preview and may change or be removed in
589 future versions of Qt.
590
591 \sa radius, topLeftRadius, bottomLeftRadius, bottomRightRadius
592*/
593qreal QQuickRectangle::topRightRadius() const
594{
595 Q_D(const QQuickRectangle);
596 if (d->extraRectangle.isAllocated() && d->extraRectangle->isTopRightRadiusSet)
597 return d->extraRectangle->topRightRadius;
598 return d->radius;
599}
600
601void QQuickRectangle::setTopRightRadius(qreal radius)
602{
603 Q_D(QQuickRectangle);
604 if (d->extraRectangle.isAllocated()
605 && d->extraRectangle->topRightRadius == radius
606 && d->extraRectangle->isTopRightRadiusSet) {
607 return;
608 }
609
610 d->extraRectangle.value().topRightRadius = radius;
611 d->extraRectangle.value().isTopRightRadiusSet = true;
612 d->maybeSetImplicitAntialiasing();
613
614 update();
615 emit topRightRadiusChanged();
616}
617
618void QQuickRectangle::resetTopRightRadius()
619{
620 Q_D(QQuickRectangle);
621 if (!d->extraRectangle.isAllocated())
622 return;
623 if (!d->extraRectangle.value().isTopRightRadiusSet)
624 return;
625
626 d->extraRectangle->isTopRightRadiusSet = false;
627 d->maybeSetImplicitAntialiasing();
628
629 update();
630 emit topRightRadiusChanged();
631}
632
633/*!
634 \since 6.7
635 \qmlproperty real QtQuick::Rectangle::bottomLeftRadius
636 This property holds the radius used to draw the bottom left corner.
637
638 If \l bottomLeftRadius is not set, \l radius will be used instead.
639 If \l bottomLeftRadius is zero, the corner will be sharp.
640
641 \note This API is considered tech preview and may change or be removed in
642 future versions of Qt.
643
644 \sa radius, topLeftRadius, topRightRadius, bottomRightRadius
645*/
646qreal QQuickRectangle::bottomLeftRadius() const
647{
648 Q_D(const QQuickRectangle);
649 if (d->extraRectangle.isAllocated() && d->extraRectangle->isBottomLeftRadiusSet)
650 return d->extraRectangle->bottomLeftRadius;
651 return d->radius;
652}
653
654void QQuickRectangle::setBottomLeftRadius(qreal radius)
655{
656 Q_D(QQuickRectangle);
657 if (d->extraRectangle.isAllocated()
658 && d->extraRectangle->bottomLeftRadius == radius
659 && d->extraRectangle->isBottomLeftRadiusSet) {
660 return;
661 }
662
663 d->extraRectangle.value().bottomLeftRadius = radius;
664 d->extraRectangle.value().isBottomLeftRadiusSet = true;
665 d->maybeSetImplicitAntialiasing();
666
667 update();
668 emit bottomLeftRadiusChanged();
669}
670
671void QQuickRectangle::resetBottomLeftRadius()
672{
673 Q_D(QQuickRectangle);
674 if (!d->extraRectangle.isAllocated())
675 return;
676 if (!d->extraRectangle.value().isBottomLeftRadiusSet)
677 return;
678
679 d->extraRectangle->isBottomLeftRadiusSet = false;
680 d->maybeSetImplicitAntialiasing();
681
682 update();
683 emit bottomLeftRadiusChanged();
684}
685
686/*!
687 \since 6.7
688 \qmlproperty real QtQuick::Rectangle::bottomRightRadius
689 This property holds the radius used to draw the bottom right corner.
690
691 If \l bottomRightRadius is not set, \l radius will be used instead.
692 If \l bottomRightRadius is zero, the corner will be sharp.
693
694 \note This API is considered tech preview and may change or be removed in
695 future versions of Qt.
696
697 \sa radius, topLeftRadius, topRightRadius, bottomLeftRadius
698*/
699qreal QQuickRectangle::bottomRightRadius() const
700{
701 Q_D(const QQuickRectangle);
702 if (d->extraRectangle.isAllocated() && d->extraRectangle->isBottomRightRadiusSet)
703 return d->extraRectangle->bottomRightRadius;
704 return d->radius;
705}
706
707void QQuickRectangle::setBottomRightRadius(qreal radius)
708{
709 Q_D(QQuickRectangle);
710 if (d->extraRectangle.isAllocated()
711 && d->extraRectangle->bottomRightRadius == radius
712 && d->extraRectangle->isBottomRightRadiusSet) {
713 return;
714 }
715
716 d->extraRectangle.value().bottomRightRadius = radius;
717 d->extraRectangle.value().isBottomRightRadiusSet = true;
718 d->maybeSetImplicitAntialiasing();
719
720 update();
721 emit bottomRightRadiusChanged();
722}
723
724void QQuickRectangle::resetBottomRightRadius()
725{
726 Q_D(QQuickRectangle);
727 if (!d->extraRectangle.isAllocated())
728 return;
729 if (!d->extraRectangle.value().isBottomRightRadiusSet)
730 return;
731
732 d->extraRectangle->isBottomRightRadiusSet = false;
733 d->maybeSetImplicitAntialiasing();
734
735 update();
736 emit bottomRightRadiusChanged();
737}
738
739/*!
740 \qmlproperty color QtQuick::Rectangle::color
741 This property holds the color used to fill the rectangle.
742
743 The default color is white.
744
745 \div {class="float-right"}
746 \inlineimage rect-color.png
747 \enddiv
748
749 The following example shows rectangles with colors specified
750 using hexadecimal and named color notation:
751
752 \snippet qml/rectangle/rectangle-colors.qml rectangles
753
754 \clearfloat
755 If both a gradient and a color are specified, the gradient will be used.
756
757 \sa gradient
758*/
759QColor QQuickRectangle::color() const
760{
761 Q_D(const QQuickRectangle);
762 return d->color;
763}
764
765void QQuickRectangle::setColor(const QColor &c)
766{
767 Q_D(QQuickRectangle);
768 if (d->color == c)
769 return;
770
771 d->color = c;
772 update();
773 emit colorChanged();
774}
775
776QSGNode *QQuickRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
777{
778 Q_UNUSED(data);
779 Q_D(QQuickRectangle);
780
781 if (width() <= 0 || height() <= 0
782 || (d->color.alpha() == 0 && (!d->pen || d->pen->width() == 0 || d->pen->color().alpha() == 0))) {
783 delete oldNode;
784 return nullptr;
785 }
786
787 QSGInternalRectangleNode *rectangle = static_cast<QSGInternalRectangleNode *>(oldNode);
788 if (!rectangle) rectangle = d->sceneGraphContext()->createInternalRectangleNode();
789
790 rectangle->setRect(QRectF(0, 0, width(), height()));
791 rectangle->setColor(d->color);
792
793 if (d->pen && d->pen->isValid()) {
794 rectangle->setPenColor(d->pen->color());
795 qreal penWidth = d->pen->width();
796 if (d->pen->pixelAligned()) {
797 qreal dpr = window() ? window()->effectiveDevicePixelRatio() : 1.0;
798 penWidth = qRound(penWidth * dpr) / dpr; // Ensures integer width after dpr scaling
799 }
800 rectangle->setPenWidth(penWidth);
801 rectangle->setAligned(false); // width rounding already done, so the Node should not do it
802 } else {
803 rectangle->setPenWidth(0);
804 }
805
806 rectangle->setRadius(d->radius);
807 if (d->extraRectangle.isAllocated()) {
808 const auto &extra = d->extraRectangle.value();
809 if (extra.isTopLeftRadiusSet)
810 rectangle->setTopLeftRadius(extra.topLeftRadius);
811 else
812 rectangle->resetTopLeftRadius();
813 if (extra.isTopRightRadiusSet)
814 rectangle->setTopRightRadius(extra.topRightRadius);
815 else
816 rectangle->resetTopRightRadius();
817 if (extra.isBottomLeftRadiusSet)
818 rectangle->setBottomLeftRadius(extra.bottomLeftRadius);
819 else
820 rectangle->resetBottomLeftRadius();
821 if (extra.isBottomRightRadiusSet)
822 rectangle->setBottomRightRadius(extra.bottomRightRadius);
823 else
824 rectangle->resetBottomRightRadius();
825 } else {
826 rectangle->resetTopLeftRadius();
827 rectangle->resetTopRightRadius();
828 rectangle->resetBottomLeftRadius();
829 rectangle->resetBottomRightRadius();
830 }
831 rectangle->setAntialiasing(antialiasing());
832
833 QGradientStops stops;
834 bool vertical = true;
835 if (d->gradient.isQObject()) {
836 auto gradient = qobject_cast<QQuickGradient*>(d->gradient.toQObject());
837 Q_ASSERT(gradient);
838 stops = gradient->gradientStops();
839 vertical = gradient->orientation() == QQuickGradient::Vertical;
840 } else if (d->gradient.isNumber() || d->gradient.isString()) {
841 QGradient preset(d->gradient.toVariant().value<QGradient::Preset>());
842 if (preset.type() == QGradient::LinearGradient) {
843 auto linearGradient = static_cast<QLinearGradient&>(preset);
844 const QPointF start = linearGradient.start();
845 const QPointF end = linearGradient.finalStop();
846 vertical = qAbs(start.y() - end.y()) >= qAbs(start.x() - end.x());
847 stops = linearGradient.stops();
848 if ((vertical && start.y() > end.y()) || (!vertical && start.x() > end.x())) {
849 // QSGInternalRectangleNode doesn't support stops in the wrong order,
850 // so we need to manually reverse them here.
851 QGradientStops reverseStops;
852 for (auto it = stops.rbegin(); it != stops.rend(); ++it) {
853 auto stop = *it;
854 stop.first = 1 - stop.first;
855 reverseStops.append(stop);
856 }
857 stops = reverseStops;
858 }
859 }
860 }
861 rectangle->setGradientStops(stops);
862 rectangle->setGradientVertical(vertical);
863
864 rectangle->update();
865
866 return rectangle;
867}
868
869QT_END_NAMESPACE
870
871#include "moc_qquickrectangle_p.cpp"
Combined button and popup list for selecting options.