aboutsummaryrefslogtreecommitdiffstats
path: root/examples/qml/tutorials/extending-qml/chapter3-bindings
diff options
context:
space:
mode:
Diffstat (limited to 'examples/qml/tutorials/extending-qml/chapter3-bindings')
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/app.qml40
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/bindings.py79
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/chapter3-bindings.pyproject3
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/doc/chapter3-bindings.rst54
4 files changed, 176 insertions, 0 deletions
diff --git a/examples/qml/tutorials/extending-qml/chapter3-bindings/app.qml b/examples/qml/tutorials/extending-qml/chapter3-bindings/app.qml
new file mode 100644
index 000000000..f1530516a
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml/chapter3-bindings/app.qml
@@ -0,0 +1,40 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import Charts
+import QtQuick
+
+Item {
+ width: 300; height: 200
+
+ Row {
+ anchors.centerIn: parent
+ spacing: 20
+
+ PieChart {
+ id: chartA
+ width: 100; height: 100
+ color: "red"
+ }
+
+ PieChart {
+ id: chartB
+ width: 100; height: 100
+ color: chartA.color
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: { chartA.color = "blue" }
+ }
+
+ Text {
+ anchors {
+ bottom: parent.bottom;
+ horizontalCenter: parent.horizontalCenter;
+ bottomMargin: 20
+ }
+ text: "Click anywhere to change the chart color"
+ }
+}
diff --git a/examples/qml/tutorials/extending-qml/chapter3-bindings/bindings.py b/examples/qml/tutorials/extending-qml/chapter3-bindings/bindings.py
new file mode 100644
index 000000000..a9b61e7f1
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml/chapter3-bindings/bindings.py
@@ -0,0 +1,79 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the qml/tutorials/extending-qml/chapter3-bindings example from Qt v5.x"""
+
+import os
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import Property, Signal, Slot, QUrl, Qt
+from PySide6.QtGui import QGuiApplication, QPen, QPainter, QColor
+from PySide6.QtQml import QmlElement
+from PySide6.QtQuick import QQuickPaintedItem, QQuickView
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "Charts"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class PieChart (QQuickPaintedItem):
+
+ chartCleared = Signal()
+ nameChanged = Signal()
+ colorChanged = Signal()
+
+ def __init__(self, parent=None):
+ QQuickPaintedItem.__init__(self, parent)
+ self._name = u''
+ self._color = QColor()
+
+ def paint(self, painter):
+ pen = QPen(self._color, 2)
+ painter.setPen(pen)
+ painter.setRenderHints(QPainter.Antialiasing, True)
+ painter.drawPie(self.boundingRect().adjusted(1, 1, -1, -1), 90 * 16, 290 * 16)
+
+ @Property(QColor, notify=colorChanged, final=True)
+ def color(self):
+ return self._color
+
+ @color.setter
+ def color(self, value):
+ if value != self._color:
+ self._color = value
+ self.update()
+ self.colorChanged.emit()
+
+ @Property(str, notify=nameChanged, final=True)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, value):
+ self._name = value
+
+ @Slot() # This should be something like @Invokable
+ def clearChart(self):
+ self.color = Qt.transparent
+ self.update()
+ self.chartCleared.emit()
+
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+
+ view = QQuickView()
+ view.setResizeMode(QQuickView.SizeRootObjectToView)
+ qml_file = os.fspath(Path(__file__).resolve().parent / 'app.qml')
+ view.setSource(QUrl.fromLocalFile(qml_file))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+ res = app.exec()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/qml/tutorials/extending-qml/chapter3-bindings/chapter3-bindings.pyproject b/examples/qml/tutorials/extending-qml/chapter3-bindings/chapter3-bindings.pyproject
new file mode 100644
index 000000000..6e21f86f9
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml/chapter3-bindings/chapter3-bindings.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["app.qml", "bindings.py"]
+}
diff --git a/examples/qml/tutorials/extending-qml/chapter3-bindings/doc/chapter3-bindings.rst b/examples/qml/tutorials/extending-qml/chapter3-bindings/doc/chapter3-bindings.rst
new file mode 100644
index 000000000..3b7191191
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml/chapter3-bindings/doc/chapter3-bindings.rst
@@ -0,0 +1,54 @@
+.. _qml-chapter3-bindings:
+
+Extending QML - Adding Property Bindings
+========================================
+
+This is the third of a series of 6 examples forming a tutorial about extending
+QML with Python.
+
+Property binding is a powerful feature of QML that allows values of different
+types to be synchronized automatically. It uses signals to notify and update
+other types' values when property values are changed.
+
+Let's enable property bindings for the ``color`` property. That means if we
+have code like this:
+
+.. literalinclude:: app.qml
+ :lineno-start: 7
+ :lines: 7-40
+
+The ``color: chartA.color`` statement binds the ``color`` value of ``chartB``
+to the ``color`` of ``chartA.`` Whenever ``chartA`` 's ``color`` value changes,
+``chartB`` 's ``color`` value updates to the same value. When the window is
+clicked, the ``onClicked`` handler in the ``MouseArea`` changes the color of
+``chartA`` , thereby changing both charts to the color blue.
+
+It's easy to enable property binding for the ``color`` property. We add a
+``notify`` parameter to its ``Property`` decorator to indicate that a
+``colorChanged`` signal is emitted whenever the value changes.
+
+.. literalinclude:: bindings.py
+ :lineno-start: 39
+ :lines: 39-39
+
+.. literalinclude:: bindings.py
+ :lineno-start: 21
+ :lines: 21-26
+
+Then, we emit this signal in ``setColor()``:
+
+.. literalinclude:: bindings.py
+ :lineno-start: 43
+ :lines: 43-48
+
+It's important for ``setColor()`` to check that the color value has actually
+changed before emitting ``colorChanged().`` This ensures the signal is not
+emitted unnecessarily and also prevents loops when other types respond to the
+value change.
+
+The use of bindings is essential to QML. You should always add ``notify``
+signals for properties if they are able to be implemented, so that your
+properties can be used in bindings. Properties that cannot be bound cannot be
+automatically updated and cannot be used as flexibly in QML. Also, since
+bindings are invoked so often and relied upon in QML usage, users of your
+custom QML types may see unexpected behavior if bindings are not implemented.