aboutsummaryrefslogtreecommitdiffstats
path: root/src/imports/controls
diff options
context:
space:
mode:
authorMitch Curtis <mitch.curtis@qt.io>2019-11-08 15:53:18 +0100
committerMitch Curtis <mitch.curtis@qt.io>2019-11-28 15:51:43 +0100
commit80f1186338bcf8c7d692b4fadfc46531c002c6b0 (patch)
tree54691e8af27b72eb49c4bec8bf543c1d13612cd3 /src/imports/controls
parent0b7358d2d24cc93160f77bac7b210cf83d404c5b (diff)
Don't delete items we didn't create
Up until this patch, we've always deleted "old" items when a new one is assigned. For example, the style's implementation of contentItem will be destroyed here as it is not accessible by the user and is no longer used: Button { contentItem: Item { /* ... */ } } This was especially important before the introduction of deferred execution, as the "default" items would always be created, regardless of whether the user had overridden it with one of their own items. By deleting the old items, we free unused resources that would otherwise persist until application shutdown (calling gc() does not result in the items being garbage-collected, from my testing). Although this has largely worked without issues, deleting objects that weren't created by us in C++ is not supported. User-assigned items can be created in QML (with JavaScriptOwnership) or C++ (with CppOwnership), and it is up to the user and/or the QML engine to manage the lifetime of these items. After the introduction of deferred execution, it became possible to skip creation of the default items altogether, meaning that there was nothing to delete when assigning a new, user-specified item. This requires that no ids are used in these items, as doing so prevents deferred execution. Assuming that users avoid using ids in their items, there should be no unused items that live unnecessarily until application shutdown. The remaining cases where items do not get destroyed when they should result from the following: - Imperative assignments (e.g. assigning an item to a Button's contentItem in Component.onCompleted). We already encourage declarative bindings rather than imperative assignments. - Using ids in items. Given that these are use cases that we will advise against in the documentation, it's an acceptable compromise. [ChangeLog][Important Behavior Changes] Old delegate items (background, contentItem, etc.) are no longer destroyed, as they are technically owned by user code. Instead, they are hidden, unparented from the control (QQuickItem parent, not QObject), and Accessible.ignored is set to true. This prevents them from being unintentionally visible and interfering with the accessibility tree when a new delegate item is set. Change-Id: I56c39a73dfee989dbe8f8b8bb33aaa187750fdb7 Task-number: QTBUG-72085 Fixes: QTBUG-70144 Fixes: QTBUG-75605 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/imports/controls')
-rw-r--r--src/imports/controls/doc/src/includes/customize-button-background.qdocinc25
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc120
2 files changed, 122 insertions, 23 deletions
diff --git a/src/imports/controls/doc/src/includes/customize-button-background.qdocinc b/src/imports/controls/doc/src/includes/customize-button-background.qdocinc
new file mode 100644
index 00000000..59df7d8e
--- /dev/null
+++ b/src/imports/controls/doc/src/includes/customize-button-background.qdocinc
@@ -0,0 +1,25 @@
+//! [file]
+\qml \QtMinorVersion
+import QtQuick 2.\1
+import QtQuick.Controls 2.\1
+
+ApplicationWindow {
+ width: 400
+ height: 400
+ visible: true
+
+ Button {
+ id: button
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: button.down ? "#d6d6d6" : "#f6f6f6"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+}
+\endqml
+//! [file]
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
index cd06a456..857e4e70 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
@@ -48,29 +48,7 @@
can override the \l {Control::}{background} item and set the radius
property of Rectangle:
- \qml \QtMinorVersion
- import QtQuick 2.\1
- import QtQuick.Controls 2.\1
-
- ApplicationWindow {
- width: 400
- height: 400
- visible: true
-
- Button {
- id: button
- text: "A Special Button"
- background: Rectangle {
- implicitWidth: 100
- implicitHeight: 40
- color: button.down ? "#d6d6d6" : "#f6f6f6"
- border.color: "#26282a"
- border.width: 1
- radius: 4
- }
- }
- }
- \endqml
+ \include customize-button-background.qdocinc file
The second way to create the button is good if you plan to use your rounded
button in several places. It involves moving the code into its own QML file
@@ -213,6 +191,102 @@
files.
\endlist
+ \section3 Considerations for custom styles
+
+ When implementing your own style and customizing controls, there are some
+ points to keep in mind to ensure that your application is as performant as
+ possible.
+
+ \section4 Avoid assigning an id to styles' implementations of item delegates
+
+ As explained in \l {Definition of a Style}, when you implement your
+ own style for a control, you start off with the relevant template for
+ that control. For example, a style's \c Button.qml will be structured
+ similarly to this:
+
+ \qml
+ T.Button {
+ // ...
+
+ background: Rectangle {
+ // ...
+ }
+
+ contentItem: Text {
+ // ...
+ }
+
+ // ...
+ }
+ \endqml
+
+ When you use a Button in your application, the \c background and
+ \c contentItem items will be created and parented to the root \c Button
+ item:
+
+ \qml
+ // Creates the Button root item, the Rectangle background,
+ // and the Text contentItem.
+ Button {
+ text: qsTr("Confirm")
+ }
+ \endqml
+
+ Suppose you then needed to do a one-off customization of the Button (as
+ explained in \l {Customizing a Control}):
+
+ \include customize-button-background.qdocinc file
+
+ In QML, this would normally result in both the default \c background
+ implementation and the one-off, custom \c background items being created.
+ Qt Quick Controls uses a technique that avoids creating both items, and
+ instead only creates the custom \c background, greatly improving the
+ creation performance of controls.
+
+ This technique relies on the absence of an \l {The id Attribute}{id} in the
+ style's implementation of that item. If an id is assigned, the technique
+ cannot work, and both items will be created. For example, it can be
+ tempting to assign an id to the \c background or \c contentItem so that
+ other objects within the file can refer to those items:
+
+ \qml
+ T.Button {
+ // ...
+
+ background: Rectangle {
+ id: backgroundRect
+ // ...
+ }
+
+ contentItem: Text {
+ // Use backgroundRect in some way...
+ }
+
+ // ...
+ }
+ \endqml
+
+ With this code, every time a Button instance with a customized background
+ is created, both backgrounds will be created, resulting in sub-optimal
+ creation performance.
+
+ Prior to Qt 5.15, the old, unused background would be deleted to release
+ the resources associated with it. However, as the control does not own the
+ items, it should not delete them. As of Qt 5.15, old items are no longer
+ deleted, and so the \c backgroundRect item will live longer than it needs
+ to—typically until the application exits. Although the old item will be
+ hidden, visually unparented from the control, and removed from the
+ accessibility tree, it is important to keep the creation time and memory
+ usage of these unused items in mind when assigning an id in this context.
+
+ \section4 Avoid imperative assignments of custom items
+
+ The technique mentioned in the section above only works when an item is
+ \l {Prefer Declarative Bindings Over Imperative Assignments}{declaratively}
+ assigned for the first time, and so imperative assignments will result in
+ orphaned items. Always use declarative bindings to assign custom items
+ when possible.
+
\section3 Attached properties
It is common for a style to have certain properties or attributes that