aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2023-05-04 12:02:21 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-05-11 10:49:31 +0000
commit667fdda3147b1556c13d6e9eab7155facbf4c0f6 (patch)
treecab571be65b4df08d29eb28f0474df68f4e6d156
parent583ece6d54c7bb9d110da372084f99cf1787b0a8 (diff)
QML basic reference examples: Add the tutorial texts
Take over the texts from C++ with adaptions for Python. Task-number: PYSIDE-2206 Task-number: QTBUG-111033 Change-Id: Iedfb9b6cd62bf467f965c94e5dbb707a88456278 Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io> (cherry picked from commit c8a2f15dc74c5b3a0cbf3f8c1891f6961578d8b2) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--examples/qml/tutorials/extending-qml/chapter1-basics/app.qml3
-rw-r--r--examples/qml/tutorials/extending-qml/chapter1-basics/doc/chapter1-basics.rst107
-rw-r--r--examples/qml/tutorials/extending-qml/chapter2-methods/app.qml3
-rw-r--r--examples/qml/tutorials/extending-qml/chapter2-methods/doc/chapter2-methods.rst36
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/app.qml3
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/doc/chapter3-bindings.rst54
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/app.qml3
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/doc/chapter4-customPropertyTypes.rst73
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/app.qml3
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/doc/chapter5-listproperties.rst46
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/doc/chapter6-plugins.rst13
11 files changed, 330 insertions, 14 deletions
diff --git a/examples/qml/tutorials/extending-qml/chapter1-basics/app.qml b/examples/qml/tutorials/extending-qml/chapter1-basics/app.qml
index 415183596..6feef5633 100644
--- a/examples/qml/tutorials/extending-qml/chapter1-basics/app.qml
+++ b/examples/qml/tutorials/extending-qml/chapter1-basics/app.qml
@@ -1,6 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-//![0]
+
import Charts
import QtQuick
@@ -24,4 +24,3 @@ Item {
text: aPieChart.name
}
}
-//![0]
diff --git a/examples/qml/tutorials/extending-qml/chapter1-basics/doc/chapter1-basics.rst b/examples/qml/tutorials/extending-qml/chapter1-basics/doc/chapter1-basics.rst
new file mode 100644
index 000000000..38233aae2
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml/chapter1-basics/doc/chapter1-basics.rst
@@ -0,0 +1,107 @@
+.. _qml-chapter1-basics:
+
+Extending QML - Creating a New Type
+===================================
+
+This is the first of a series of 6 examples forming a tutorial
+about extending QML with Python.
+
+The Qt QML module provides a set of APIs for extending QML through Python
+extensions. You can write extensions to add your own QML types, extend existing
+Qt types, or call Python functions that are not accessible from ordinary QML
+code.
+
+This tutorial shows how to write a QML extension using Python that includes
+core QML features, including properties, signals and bindings. It also shows
+how extensions can be deployed through plugins.
+
+A common task when extending QML is to provide a new QML type that supports
+some custom functionality beyond what is provided by the built-in Qt Quick
+types. For example, this could be done to implement particular data models, or
+provide types with custom painting and drawing capabilities, or access system
+features like network programming that are not accessible through built-in QML
+features.
+
+In this tutorial, we will show how to use the C++ classes in the Qt Quick
+module to extend QML. The end result will be a simple Pie Chart display
+implemented by several custom QML types connected together through QML features
+like bindings and signals, and made available to the QML runtime through a
+plugin.
+
+To begin with, let's create a new QML type called ``PieChart`` that has two
+properties: a name and a color. We will make it available in an importable type
+namespace called ``Charts``, with a version of 1.0.
+
+We want this ``PieChart`` type to be usable from QML like this:
+
+.. code-block:: javascript
+
+ import Charts 1.0
+
+ PieChart {
+ width: 100; height: 100
+ name: "A simple pie chart"
+ color: "red"
+ }
+
+To do this, we need a C++ class that encapsulates this ``PieChart`` type and
+its two properties. Since QML makes extensive use of Qt's Meta-Object System
+this new class must:
+
+* Inherit from ``QObject``
+* Declare its properties using the ``Property`` decorator
+
+Class Implementation
+--------------------
+
+Here is our ``PieChart`` class, defined in ``basics.py``:
+
+.. literalinclude:: basics.py
+ :lineno-start: 21
+ :lines: 21-51
+
+The class inherits from ``QQuickPaintedItem`` because we want to override
+``QQuickPaintedItem.paint()`` to perform drawing operations with the
+``QPainter`` API. If the class just represented some data type and was not an
+item that actually needed to be displayed, it could simply inherit from
+``QObject``. Or, if we want to extend the functionality of an existing
+``QObject``-based class, it could inherit from that class instead.
+Alternatively, if we want to create a visual item that doesn't need to perform
+drawing operations with the ``QPainter`` API, we can just subclass
+``QQuickItem``.
+
+The ``PieChart`` class defines the two properties, ``name`` and ``color``, with
+the ``Property`` decorator, and overrides ``QQuickPaintedItem.paint()``. The
+``PieChart`` class is registered using the ``QmlElement`` decorator, to allow
+it to be used from QML. If you don't register the class, ``app.qml`` won't be
+able to create a ``PieChart``.
+
+QML Usage
+---------
+
+Now that we have defined the ``PieChart`` type, we will use it from QML. The
+``app.qml`` file creates a ``PieChart`` item and displays the pie chart's details
+using a standard QML ``Text`` item:
+
+.. literalinclude:: app.qml
+ :lineno-start: 7
+ :lines: 7-26
+
+Notice that although the color is specified as a string in QML, it is
+automatically converted to a ``QColor`` object for the PieChart ``color``
+property. Automatic conversions are provided for various other QML value types.
+For example, a string like "640x480" can be automatically converted to a
+``QSize`` value.
+
+We'll also create a main function that uses a ``QQuickView`` to run and display
+``app.qml``. Here is the application ``basics.py``:
+
+.. literalinclude:: basics.py
+ :lineno-start: 54
+ :lines: 54-68
+
+.. note:: You may see a warning `Expression ... depends on non-NOTIFYable properties:
+ PieChart.name`. This happens because we add a binding to the writable ``name``
+ property, but haven't yet defined a notify signal for it. The QML engine therefore
+ cannot update the binding if the ``name`` value changes. This is addressed in
+ the following chapters.
diff --git a/examples/qml/tutorials/extending-qml/chapter2-methods/app.qml b/examples/qml/tutorials/extending-qml/chapter2-methods/app.qml
index d330f3b64..d9477e253 100644
--- a/examples/qml/tutorials/extending-qml/chapter2-methods/app.qml
+++ b/examples/qml/tutorials/extending-qml/chapter2-methods/app.qml
@@ -1,6 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-//![0]
+
import Charts
import QtQuick
@@ -30,4 +30,3 @@ Item {
text: "Click anywhere to clear the chart"
}
}
-//![0]
diff --git a/examples/qml/tutorials/extending-qml/chapter2-methods/doc/chapter2-methods.rst b/examples/qml/tutorials/extending-qml/chapter2-methods/doc/chapter2-methods.rst
new file mode 100644
index 000000000..245d0ddb2
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml/chapter2-methods/doc/chapter2-methods.rst
@@ -0,0 +1,36 @@
+.. _qml-chapter2-methods:
+
+Extending QML - Connecting to C++ Methods and Signals
+=====================================================
+
+This is the second of a series of 6 examples forming a tutorial about extending
+QML with Python.
+
+Suppose we want ``PieChart`` to have a ``clearChart()`` method that erases the
+chart and then emits a ``chartCleared`` signal. Our ``app.qml`` would be able
+to call ``clearChart()`` and receive ``chartCleared()`` signals like this:
+
+.. literalinclude:: app.qml
+ :lineno-start: 4
+ :lines: 4-32
+
+To do this, we add a ``clearChart()`` method and a ``chartCleared()`` signal
+to our C++ class:
+
+.. literalinclude:: methods.py
+ :lineno-start: 54
+ :lines: 54-58
+
+The use of the ``Slot`` decorator makes the ``clearChart()`` method available
+to the Qt Meta-Object system, and in turn, to QML. The method simply changes
+the color to ``Qt::transparent``, repaints the chart, then emits the
+``chartCleared()`` signal:
+
+.. literalinclude:: methods.py
+ :lineno-start: 21
+ :lines: 21-24
+
+Now when we run the application and click the window, the pie chart disappears,
+and the application outputs::
+
+ qml: The chart has been cleared
diff --git a/examples/qml/tutorials/extending-qml/chapter3-bindings/app.qml b/examples/qml/tutorials/extending-qml/chapter3-bindings/app.qml
index ee24a428a..f1530516a 100644
--- a/examples/qml/tutorials/extending-qml/chapter3-bindings/app.qml
+++ b/examples/qml/tutorials/extending-qml/chapter3-bindings/app.qml
@@ -1,6 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-//![0]
+
import Charts
import QtQuick
@@ -38,4 +38,3 @@ Item {
text: "Click anywhere to change the chart color"
}
}
-//![0]
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.
diff --git a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/app.qml b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/app.qml
index 954e6465c..a5c5ff9fa 100644
--- a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/app.qml
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/app.qml
@@ -1,6 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-//![0]
+
import Charts
import QtQuick
@@ -20,4 +20,3 @@ Item {
Component.onCompleted: console.log("The pie is colored " + chart.pieSlice.color)
}
-//![0]
diff --git a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/doc/chapter4-customPropertyTypes.rst b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/doc/chapter4-customPropertyTypes.rst
new file mode 100644
index 000000000..f7c3efb11
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/doc/chapter4-customPropertyTypes.rst
@@ -0,0 +1,73 @@
+.. _qml-chapter4-custompropertytypes:
+
+Extending QML - Using Custom Property Types
+===========================================
+
+This is the fourth of a series of 6 examples forming a tutorial about extending
+QML with Python.
+
+The ``PieChart`` type currently has a string-type property and a color-type property.
+It could have many other types of properties. For example, it could have an
+int-type property to store an identifier for each chart:
+
+.. code-block:: python
+
+ class PieChart(QQuickPaintedItem):
+ chartIdChanged = Signal()
+
+ @Property(int, notify=chartIdChanged)
+ def chartId(self):
+ pass
+
+ @chartId.setter
+ def setChartId(self, chartId):
+ pass
+
+.. code-block:: javascript
+
+ // QML
+ PieChart {
+ ...
+ chartId: 100
+ }
+
+Aside from ``int``, we could use various other property types. Many of the Qt
+data types such as ``QColor``, ``QSize`` and ``QRect`` are automatically
+supported from QML.
+
+If we want to create a property whose type is not supported by QML by default,
+we need to register the type with the QML engine.
+
+For example, let's replace the use of the ``property`` with a type called
+``PieSlice`` that has a ``color`` property. Instead of assigning a color,
+we assign an ``PieSlice`` value which itself contains a ``color``:
+
+.. literalinclude:: app.qml
+ :lineno-start: 4
+ :lines: 4-22
+
+Like ``PieChart``, this new ``PieSlice`` type inherits from
+``QQuickPaintedItem``, is exposed via the ``QmlElement`` decorator and declares
+its properties with the ``Property`` decorator:
+
+.. literalinclude:: customPropertyTypes.py
+ :lineno-start: 21
+ :lines: 21-40
+
+To use it in ``PieChart``, we modify the ``color`` property declaration
+and associated method signatures:
+
+.. literalinclude:: customPropertyTypes.py
+ :lineno-start: 58
+ :lines: 58-65
+
+There is one thing to be aware of when implementing ``setPieSlice()``. The
+``PieSlice`` is a visual item, so it must be set as a child of the ``PieChart``
+using ``QQuickItem.setParentItem()`` so that the ``PieChart`` knows to paint
+this child item when its contents are drawn.
+
+As with ``PieChart``, we add the ``Charts`` type namespace, version 1.0:
+
+.. literalinclude:: customPropertyTypes.py
+ :lineno-start: 15
+ :lines: 15-18
diff --git a/examples/qml/tutorials/extending-qml/chapter5-listproperties/app.qml b/examples/qml/tutorials/extending-qml/chapter5-listproperties/app.qml
index edbf3e770..ac99d5a40 100644
--- a/examples/qml/tutorials/extending-qml/chapter5-listproperties/app.qml
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/app.qml
@@ -1,6 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-//![0]
+
import Charts
import QtQuick
@@ -30,4 +30,3 @@ Item {
]
}
}
-//![0]
diff --git a/examples/qml/tutorials/extending-qml/chapter5-listproperties/doc/chapter5-listproperties.rst b/examples/qml/tutorials/extending-qml/chapter5-listproperties/doc/chapter5-listproperties.rst
new file mode 100644
index 000000000..90cb41107
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/doc/chapter5-listproperties.rst
@@ -0,0 +1,46 @@
+.. _qml-chapter5-listproperties:
+
+Extending QML - Using List Property Types
+=========================================
+
+This is the fifth of a series of 6 examples forming a tutorial about extending
+QML with Python.
+
+Right now, a ``PieChart`` can only have one ``PieSlice.`` Ideally a chart would
+have multiple slices, with different colors and sizes. To do this, we could
+have a ``slices`` property that accepts a list of ``PieSlice`` items:
+
+.. literalinclude:: app.qml
+ :lineno-start: 4
+ :lines: 4-32
+
+To do this, we replace the ``pieSlice`` property in ``PieChart`` with a
+``slices`` property, declared as a class variable of the ``QQmlListProperty``
+type. The ``QQmlListProperty`` class enables the creation of list properties in
+QML extensions. We replace the ``pieSlice()`` function with a ``slices()``
+function that returns a list of slices, and add an internal ``appendSlice()``
+function (discussed below). We also use a list to store the internal list of
+slices as ``_slices``:
+
+.. literalinclude:: listproperties.py
+ :lineno-start: 62
+ :lines: 62-65
+
+.. literalinclude:: listproperties.py
+ :lineno-start: 75
+ :lines: 75-79
+
+Although the ``slices`` property does not have an associated setter, it is
+still modifiable because of the way ``QQmlListProperty`` works. We indicate
+that the internal ``PieChart.appendSlice()`` function is to be called whenever
+a request is made from QML to add items to the list.
+
+The ``appendSlice()`` function simply sets the parent item as before, and adds
+the new item to the ``_slices`` list. As you can see, the append function for
+a ``QQmlListProperty`` is called with two arguments: the list property, and the
+item that is to be appended.
+
+The ``PieSlice`` class has also been modified to include ``fromAngle`` and
+``angleSpan`` properties and to draw the slice according to these values. This
+is a straightforward modification if you have read the previous pages in this
+tutorial, so the code is not shown here.
diff --git a/examples/qml/tutorials/extending-qml/chapter6-plugins/doc/chapter6-plugins.rst b/examples/qml/tutorials/extending-qml/chapter6-plugins/doc/chapter6-plugins.rst
index aeffd7e9a..a9d100812 100644
--- a/examples/qml/tutorials/extending-qml/chapter6-plugins/doc/chapter6-plugins.rst
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/doc/chapter6-plugins.rst
@@ -3,10 +3,15 @@
Extending QML - Plugins Example
===============================
-This example refers to the Python version of using a QML plugin in Python. The idea of plugins in
-Python is non-existent because Python modules are dynamically loaded anyway. We use this idea and
-our QML type registration decorators - QmlELement/QmlNamedElement - to register the QML modules as
-they are imported. The pyside6-qml tool does this for you by simply pointing to the .qml file.
+This is the last of a series of 6 examples forming a tutorial
+about extending QML with Python.
+
+This example refers to the Python version of using a QML plugin in Python. The
+idea of plugins in Python is non-existent because Python modules are
+dynamically loaded anyway. We use this idea and our QML type registration
+decorators - ``QmlELement``/``QmlNamedElement`` - to register the QML modules as they
+are imported. The ``pyside6-qml`` tool does this for you by simply pointing to the
+``.qml`` file.
.. image:: plugins.png
:width: 400