Escribir extensiones QML con C++
El módulo Qt Qml proporciona un conjunto de API para ampliar QML mediante extensiones C++. Puedes escribir extensiones para añadir tus propios tipos QML, extender tipos Qt existentes, o llamar a funciones C/C++ que no son accesibles desde el código QML ordinario.
Este tutorial muestra cómo escribir una extensión QML utilizando C++ que incluya las características principales de QML, incluyendo propiedades, señales y enlaces. También muestra cómo se pueden desplegar extensiones a través de plugins.
Muchos de los temas tratados en este tutorial se documentan con más detalle en Visión general - Integración de QML y C++ y sus subtemas de documentación. En particular, pueden interesarle los subtemas Exposición de atributos de clases C++ a QML y Definición de tipos QML desde C++.
Abrir las fuentes del tutorial
El código de este tutorial está disponible como parte de las fuentes de Qt. Si instalaste Qt con Qt Online Installer, puedes encontrar los fuentes en el directorio de instalación de Qt bajo Examples/Qt-6.11.0/qml/tutorials/extending-qml/.
Crear un proyecto desde cero
Alternativamente, puedes seguir el tutorial creando los fuentes desde cero: Para cada capítulo, cree un nuevo proyecto utilizando la plantilla Qt Quick Application en Qt Creator, como se indica en Qt Creator: Crear Qt Quick Aplicaciones. A continuación, siga el tutorial adaptando y ampliando el esqueleto de código generado.
Capítulo 1: Creación de un nuevo tipo
extending-qml/chapter1-basics
Una tarea común al extender QML es proporcionar un nuevo tipo QML que soporte alguna funcionalidad personalizada más allá de lo que proporciona el tipo incorporado Qt Quick types. Por ejemplo, esto podría hacerse para implementar modelos de datos particulares, o proporcionar tipos con capacidades personalizadas de pintura y dibujo, o acceder a características del sistema como la programación en red que no son accesibles a través de las características incorporadas en QML.
En este tutorial, mostraremos cómo utilizar las clases C++ en el módulo Qt Quick para extender QML. El resultado final será un simple gráfico circular implementado por varios tipos QML personalizados conectados entre sí a través de características QML como enlaces y señales, y puestos a disposición del tiempo de ejecución QML a través de un plugin.
Para empezar, vamos a crear un nuevo tipo QML llamado "PieChart" que tiene dos propiedades: un nombre y un color. Lo haremos disponible en un espacio de nombres de tipo importable llamado "Charts", con una versión de 1.0.
Queremos que este tipo PieChart sea utilizable desde QML de esta forma:
import Charts PieChart { width: 100; height: 100 name: "A simple pie chart" color: "red" }
Para ello, necesitamos una clase C++ que encapsule este tipo PieChart y sus propiedades. Dado que QML hace un uso extensivo del meta sistema de objetos de Qt, esta nueva clase debe:
- Heredar de QObject
- Declarar sus propiedades utilizando la macro Q_PROPERTY
Declaración de la clase
Aquí está nuestra clase PieChart, definida en piechart.h:
#include <QtQuick/QQuickPaintedItem> #include <QColor> class PieChart : public QQuickPaintedItem { Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName FINAL) Q_PROPERTY(QColor color READ color WRITE setColor FINAL) QML_ELEMENT public: PieChart(QQuickItem *parent = nullptr); QString name() const; void setName(const QString &name); QColor color() const; void setColor(const QColor &color); void paint(QPainter *painter) override; private: QString m_name; QColor m_color; };
La clase hereda de QQuickPaintedItem porque queremos sobreescribir QQuickPaintedItem::paint() para realizar operaciones de dibujo con la API QPainter. Si la clase sólo representara algún tipo de dato y no fuera un elemento que realmente necesitara ser mostrado, podría simplemente heredar de QObject. O, si queremos ampliar la funcionalidad de una clase existente basada en QObject, podría heredar de esa clase. Alternativamente, si queremos crear un elemento visual que no necesite realizar operaciones de dibujo con la API QPainter, podemos simplemente subclasificar QQuickItem.
La clase PieChart define las dos propiedades, name y color, con la macro Q_PROPERTY, y anula QQuickPaintedItem::paint(). La clase PieChart se registra mediante la macro QML_ELEMENT, para poder utilizarla desde QML. Si no se registra la clase, App.qml no podrá crear un PieChart.
Configuración de qmake
Para que el registro surta efecto, se añade la opción qmltypes a CONFIG en el fichero de proyecto y se proporcionan QML_IMPORT_NAME y QML_IMPORT_MAJOR_VERSION:
CONFIG += qmltypes QML_IMPORT_NAME = Charts QML_IMPORT_MAJOR_VERSION = 1
Además, es necesario añadir manualmente un archivo qmldir para crear un módulo QML.
module Charts typeinfo chapter1-basics.qmltypes depends QtQuick prefer :/qt/qml/Charts/ App 254.0 App.qml
Configuración de CMake
Para que el registro tenga efecto al utilizar CMake, utilice el comando qt_add_qml_module:
qt_add_qml_module(chapter1-basics
URI Charts
QML_FILES App.qml
DEPENDENCIES QtQuick
)La API qt_add_qml_module genera automáticamente un archivo qmldir para el módulo QML.
Implementación de clases
La implementación de la clase en piechart.cpp simplemente establece y devuelve los valores m_name y m_color según corresponda, e implementa paint() para dibujar un gráfico circular simple:
PieChart::PieChart(QQuickItem *parent) : QQuickPaintedItem(parent) { } ... void PieChart::paint(QPainter *painter) { QPen pen(m_color, 2); painter->setPen(pen); painter->setRenderHints(QPainter::Antialiasing, true); painter->drawPie(boundingRect().adjusted(1, 1, -1, -1), 90 * 16, 290 * 16); }
Uso de QML
Ahora que hemos definido el tipo PieChart, vamos a utilizarlo desde QML. El archivo App.qml crea un elemento PieChart y muestra los detalles del gráfico circular utilizando un elemento QML estándar Text:
import Charts import QtQuick Item { width: 300; height: 200 PieChart { id: aPieChart anchors.centerIn: parent width: 100; height: 100 name: "A simple pie chart" color: "red" } Text { anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter; bottomMargin: 20 } text: aPieChart.name } }
Observe que aunque el color se especifica como una cadena en QML, se convierte automáticamente en un objeto QColor para la propiedad PieChart color. Existen conversiones automáticas para otros tipos de valores. Por ejemplo, una cadena como "640x480" puede convertirse automáticamente en un valor QSize.
También crearemos una aplicación C++ que utiliza un QQuickView para ejecutar y mostrar App.qml.
Aquí está la aplicación main.cpp:
#include "piechart.h" #include <QtQuick/QQuickView> #include <QGuiApplication> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQuickView view; view.setResizeMode(QQuickView::SizeRootObjectToView); view.loadFromModule("Charts", "App"); view.show(); return QGuiApplication::exec(); }
Construcción del proyecto
Para construir el proyecto incluimos los ficheros, enlazamos con las librerías, y definimos un espacio de nombres de tipos llamado "Charts" con versión 1.0 para cualquier tipo expuesto a QML.
Usando qmake:
QT += qml quick
CONFIG += qmltypes
QML_IMPORT_NAME = Charts
QML_IMPORT_MAJOR_VERSION = 1
HEADERS += piechart.h
SOURCES += piechart.cpp \
main.cpp
RESOURCES += chapter1-basics.qrc
DESTPATH = $$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending-qml/chapter1-basics
target.path = $$DESTPATH
INSTALLS += targetUsando CMake:
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(chapter1-basics LANGUAGES CXX)
find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick)
qt_standard_project_setup(REQUIRES 6.8)
qt_add_executable(chapter1-basics
main.cpp
piechart.cpp piechart.h
)
set_target_properties(chapter1-basics PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(chapter1-basics PUBLIC
Qt6::Core
Qt6::Gui
Qt6::Qml
Qt6::Quick
)
qt_add_qml_module(chapter1-basics
URI Charts
QML_FILES App.qml
DEPENDENCIES QtQuick
)
install(TARGETS chapter1-basics
BUNDLE DESTINATION .
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
qt_generate_deploy_qml_app_script(
TARGET chapter1-basics
OUTPUT_SCRIPT deploy_script
MACOS_BUNDLE_POST_BUILD
NO_UNSUPPORTED_PLATFORM_ERROR
DEPLOY_USER_QML_MODULES_ON_UNSUPPORTED_PLATFORM
)
install(SCRIPT ${deploy_script})Ahora podemos construir y ejecutar la aplicación:

Nota: Es posible que aparezca una advertencia Expression ... depende de propiedades no vinculables: PieChart::name. Esto ocurre porque añadimos un enlace a la propiedad escribible name, pero aún no hemos definido una señal de notificación para ella. Por tanto, el motor QML no puede actualizar el enlace si cambia el valor de name. Esta cuestión se aborda en los capítulos siguientes.
Capítulo 2: Conexión a métodos y señales de C
extending-qml/chapter2-methods
Supongamos que queremos que PieChart tenga un método "clearChart()" que borre el gráfico y emita una señal "chartCleared". Nuestro App.qml podría llamar a clearChart() y recibir señales de chartCleared() de esta manera:
import Charts import QtQuick Item { width: 300; height: 200 PieChart { id: aPieChart anchors.centerIn: parent width: 100; height: 100 color: "red" onChartCleared: console.log("The chart has been cleared") } MouseArea { anchors.fill: parent onClicked: aPieChart.clearChart() } Text { anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter; bottomMargin: 20 } text: "Click anywhere to clear the chart" } }

Para ello, añadimos un método clearChart() y una señal chartCleared() a nuestra clase C++:
class PieChart : public QQuickPaintedItem { ... public: ... Q_INVOKABLE void clearChart(); signals: void chartCleared(); ... };
El uso de Q_INVOKABLE hace que el método clearChart() esté disponible para el sistema de Meta-Objetos de Qt, y a su vez, para QML.
Nota: También puedes declarar el método como un slot de Qt en lugar de usar Q_INVOKABLE, porque los slots públicos y protegidos también son invocables desde QML (no puedes invocar slots privados).
El método clearChart() cambia el color a Qt::transparent, repinta el gráfico y emite la señal chartCleared():
Ahora, cuando ejecutamos la aplicación y hacemos clic en la ventana, el gráfico circular desaparece y la aplicación sale:
qml: The chart has been cleared
Capítulo 3: Añadir enlaces de propiedades
extending-qml/chapter3-bindings
La vinculación de propiedades es una potente característica de QML que permite sincronizar automáticamente valores de diferentes tipos. Utiliza señales para notificar y actualizar los valores de otros tipos cuando cambian los valores de las propiedades.
Vamos a activar los enlaces de propiedad para la propiedad color. Eso significa que si tenemos código como este
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" } }

La sentencia "color: chartA.color" vincula el valor color de chartB al color de chartA. Cada vez que cambia el valor color de chartA, el valor color de chartB se actualiza al mismo valor. Cuando se hace clic en la ventana, el manejador onClicked en MouseArea cambia el color de chartA, cambiando así ambos gráficos al color azul.
Es fácil habilitar la vinculación de propiedades para la propiedad color. Añadimos una función NOTIFY a su declaración Q_PROPERTY() para indicar que se emita una señal "colorChanged" cada vez que cambie el valor.
class PieChart : public QQuickPaintedItem { ... Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged FINAL) public: ... signals: void colorChanged(); ... };
A continuación, emitimos esta señal en setColor():
void PieChart::setColor(const QColor &color) { if (color != m_color) { m_color = color; update(); // repaint with the new color emit colorChanged(); } }
Es importante que setColor() compruebe que el valor del color ha cambiado realmente antes de emitir colorChanged(). Esto asegura que la señal no se emite innecesariamente y también evita bucles cuando otros tipos responden al cambio de valor.
El uso de bindings es esencial para QML. Siempre debe añadir señales NOTIFY para las propiedades si se pueden implementar, de modo que sus propiedades se puedan utilizar en las vinculaciones. Las propiedades que no se pueden vincular no se pueden actualizar automáticamente y no se pueden utilizar con la misma flexibilidad en QML. Además, dado que los bindings se invocan con tanta frecuencia y se depende de ellos en el uso de QML, los usuarios de sus tipos QML personalizados pueden ver comportamientos inesperados si los bindings no están implementados.
Capítulo 4: Uso de tipos de propiedad personalizados
extending-qml/chapter4-customPropertyTypes
El tipo PieChart tiene actualmente una propiedad de tipo cadena y una propiedad de tipo color. Podría tener muchos otros tipos de propiedades. Por ejemplo, podría tener una propiedad de tipo int para almacenar un identificador para cada gráfico:
// C++ class PieChart : public QQuickPaintedItem { Q_PROPERTY(int chartId READ chartId WRITE setChartId NOTIFY chartIdChanged) ... public: void setChartId(int chartId); int chartId() const; ... signals: void chartIdChanged(); }; // QML PieChart { ... chartId: 100 }
Aparte de int, podríamos utilizar otros tipos de propiedades. Muchos de los tipos de datos Qt como QColor, QSize y QRect son automáticamente soportados desde QML. (Consulte la documentación Conversión de tipos de datos entre QML y C++ para obtener una lista completa).
Si queremos crear una propiedad cuyo tipo no está soportado por QML por defecto, necesitamos registrar el tipo con el motor QML.
Por ejemplo, sustituyamos el uso de property por un tipo llamado "PieSlice" que tenga una propiedad color. En lugar de asignar un color, asignamos un valor PieSlice que a su vez contiene un color:
import Charts import QtQuick Item { width: 300; height: 200 PieChart { id: chart anchors.centerIn: parent width: 100; height: 100 pieSlice: PieSlice { anchors.fill: parent color: "red" } } Component.onCompleted: console.log("The pie is colored " + chart.pieSlice.color) }
Al igual que PieChart, este nuevo tipo PieSlice hereda de QQuickPaintedItem y declara sus propiedades con Q_PROPERTY():
class PieSlice : public QQuickPaintedItem { Q_OBJECT Q_PROPERTY(QColor color READ color WRITE setColor FINAL) QML_ELEMENT public: PieSlice(QQuickItem *parent = nullptr); QColor color() const; void setColor(const QColor &color); void paint(QPainter *painter) override; private: QColor m_color; };
Para utilizarlo en PieChart, modificamos la declaración de propiedades color y las firmas de los métodos asociados:
class PieChart : public QQuickItem { Q_OBJECT Q_PROPERTY(PieSlice* pieSlice READ pieSlice WRITE setPieSlice FINAL) ... public: ... PieSlice *pieSlice() const; void setPieSlice(PieSlice *pieSlice); ... };
Hay una cosa que hay que tener en cuenta al implementar setPieSlice(). El PieSlice es un elemento visual, por lo que debe establecerse como hijo del PieChart utilizando QQuickItem::setParentItem() para que el PieChart sepa que debe pintar este elemento hijo cuando se dibuje su contenido:
void PieChart::setPieSlice(PieSlice *pieSlice) { m_pieSlice = pieSlice; pieSlice->setParentItem(this); }
Al igual que el tipo PieChart, el tipo PieSlice tiene que ser expuesto a QML usando QML_ELEMENT.
class PieSlice : public QQuickPaintedItem { Q_OBJECT Q_PROPERTY(QColor color READ color WRITE setColor FINAL) QML_ELEMENT public: PieSlice(QQuickItem *parent = nullptr); QColor color() const; void setColor(const QColor &color); void paint(QPainter *painter) override; private: QColor m_color; }; ...
Al igual que con PieChart, añadimos el espacio de nombres del tipo "Charts", versión 1.0, a nuestro archivo de compilación:
Usando qmake:
QT += qml quick
CONFIG += qmltypes
QML_IMPORT_NAME = Charts
QML_IMPORT_MAJOR_VERSION = 1
HEADERS += piechart.h \
pieslice.h
SOURCES += piechart.cpp \
pieslice.cpp \
main.cpp
RESOURCES += chapter4-customPropertyTypes.qrc
DESTPATH = $$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending-qml/chapter4-customPropertyTypes
target.path = $$DESTPATH
INSTALLS += targetUsando CMake:
...
qt_add_executable(chapter4-customPropertyTypes
main.cpp
piechart.cpp piechart.h
pieslice.cpp pieslice.h
)
qt_add_qml_module(chapter4-customPropertyTypes
URI Charts
QML_FILES App.qml
DEPENDENCIES QtQuick
)
...Capítulo 5: Uso de tipos de propiedades de lista
extending-qml/chapter5-listproperties
Ahora mismo, un PieChart sólo puede tener un PieSlice. Lo ideal sería que un gráfico tuviera varios cortes, con diferentes colores y tamaños. Para ello, podríamos tener una propiedad slices que acepte una lista de elementos PieSlice:
pragma ComponentBehavior: Bound import Charts import QtQuick Item { width: 300; height: 200 PieChart { id: chart anchors.centerIn: parent width: 100; height: 100 component Slice: PieSlice { parent: chart anchors.fill: parent } slices: [ Slice { color: "red" fromAngle: 0 angleSpan: 110 }, Slice { color: "black" fromAngle: 110 angleSpan: 50 }, Slice { color: "blue" fromAngle: 160 angleSpan: 100 } ] } }

Para ello, sustituimos la propiedad pieSlice de PieChart por una propiedad slices, declarada como una clase QQmlListProperty. La clase QQmlListProperty permite crear propiedades de lista en tipos expuestos a QML. Sustituimos la función pieSlice() por una función slices() que devuelve una lista de slices. También utilizamos un QList para almacenar la lista interna de rebanadas como m_slices:
class PieChart : public QQuickItem { Q_OBJECT Q_PROPERTY(QQmlListProperty<PieSlice> slices READ slices FINAL) ... public: ... QQmlListProperty<PieSlice> slices(); private: QString m_name; QList<PieSlice *> m_slices; };
Aunque la propiedad slices no tiene una función WRITE asociada, sigue siendo modificable debido a la forma en que funciona QQmlListProperty. En la implementación de PieChart, implementamos PieChart::slices() para devolver un valor QQmlListProperty:
QQmlListProperty<PieSlice> PieChart::slices() { return QQmlListProperty<PieSlice>(this, &m_slices); }
Esto sintetiza las funciones necesarias para interactuar con la lista desde QML. El resultado QQmlListProperty es una vista de la lista. Alternativamente, puede proporcionar manualmente las funciones de acceso individuales para la lista. Esto es necesario si la lista no es QList o si desea restringir o personalizar de algún modo el acceso de QML a la lista. En la mayoría de los casos, sin embargo, el constructor que toma un puntero QList es la opción más segura y sencilla.
La clase PieSlice también se ha modificado para incluir las propiedades fromAngle y angleSpan y para dibujar la rebanada de acuerdo con estos valores. Esta es una modificación sencilla si has leído las páginas anteriores de este tutorial, por lo que el código no se muestra aquí.
Capítulo 6: Escribiendo un Plugin de Extensión
extending-qml/chapter6-plugins
Actualmente los tipos PieChart y PieSlice son utilizados por App.qml, que se muestra utilizando un QQuickView en una aplicación C++. Una forma alternativa de utilizar nuestra extensión QML es crear una biblioteca plugin para ponerla a disposición del motor QML como un nuevo módulo de importación QML. Esto permite que los tipos PieChart y PieSlice se registren en un espacio de nombres de tipos que puede ser importado por cualquier aplicación QML, en lugar de restringir estos tipos para que sólo sean utilizados por una aplicación.
Los pasos para crear un plugin se describen en Creación de plugins C++ para QML. Para empezar, creamos una clase plugin llamada ChartsPlugin. Subclase QQmlEngineExtensionPlugin y utiliza la macro Q_PLUGIN_METADATA() para registrar el plugin con el sistema de meta-objetos Qt.
Aquí está la definición de ChartsPlugin en chartsplugin.h:
#include <QQmlEngineExtensionPlugin> class ChartsPlugin : public QQmlEngineExtensionPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid) };
A continuación, configuramos el archivo de compilación para definir el proyecto como una biblioteca de plugins.
Usando qmake:
TEMPLATE = lib
CONFIG += plugin qmltypes
QT += qml quick
QML_IMPORT_NAME = Charts
QML_IMPORT_MAJOR_VERSION = 1
TARGET = $$qtLibraryTarget(chartsplugin)
HEADERS += piechart.h \
pieslice.h \
chartsplugin.h
SOURCES += piechart.cpp \
pieslice.cpp
DESTPATH=$$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending-qml/chapter6-plugins/$$QML_IMPORT_NAME
target.path=$$DESTPATH
qmldir.files=$$PWD/qmldir
qmldir.path=$$DESTPATH
INSTALLS += target qmldir
CONFIG += install_ok # Do not cargo-cult this!
OTHER_FILES += qmldir
# Copy the qmldir file to the same folder as the plugin binary
cpqmldir.files = qmldir
cpqmldir.path = .
COPIES += cpqmldirUsando CMake:
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
qt6_policy(SET QTP0001 NEW)
qt6_add_qml_module(chartsplugin
URI "Charts"
PLUGIN_TARGET chartsplugin
DEPENDENCIES QtQuick
)
target_sources(chartsplugin PRIVATE
piechart.cpp piechart.h
pieslice.cpp pieslice.h
)
target_link_libraries(chartsplugin PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Qml
Qt6::Quick
)
install(TARGETS chartsplugin
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}/Charts"
LIBRARY DESTINATION "${CMAKE_INSTALL_BINDIR}/Charts"
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qmldir
DESTINATION "${CMAKE_INSTALL_BINDIR}/Charts"
)Al construir este ejemplo en Windows o Linux, el directorio Charts se ubicará en el mismo nivel que la aplicación que utiliza nuestro nuevo módulo de importación. De esta forma, el motor QML encontrará nuestro módulo ya que la ruta de búsqueda por defecto para importaciones QML incluye el directorio del ejecutable de la aplicación. En macOS, el binario del plugin se copia en Contents/PlugIns en el paquete de la aplicación. Con qmake, esta ruta se establece en chapter6-plugins/app.pro:
macos:!qtConfig(static) {
charts.files = $$OUT_PWD/Charts
charts.path = Contents/PlugIns
QMAKE_BUNDLE_DATA += charts
}Para tener esto en cuenta, también tenemos que añadir esta ubicación como ruta de importación QML en main.cpp:
QQuickView view; #ifdef Q_OS_MACOS view.engine()->addImportPath(app.applicationDirPath() + "/../PlugIns"); #endif ...
Definir rutas de importación personalizadas es útil también cuando hay varias aplicaciones que utilizan las mismas importaciones QML.
El archivo .pro también contiene magia adicional para garantizar que el archivo qmldir de definición del módulo siempre se copie en la misma ubicación que el binario del complemento.
El archivo qmldir declara el nombre del módulo y el plugin que el módulo pone a disposición:
module Charts optional plugin chartsplugin typeinfo plugins.qmltypes depends QtQuick prefer :/qt/qml/Charts/
Ahora tenemos un módulo QML que puede ser importado a cualquier aplicación, siempre que el motor QML sepa dónde encontrarlo. El ejemplo contiene un ejecutable que carga App.qml, que utiliza la sentencia import Charts 1.0. Alternativamente, puede cargar el archivo QML utilizando la herramienta qml, estableciendo la ruta de importación en el directorio actual para que encuentre el archivo qmldir:
qml -I . App.qml
El módulo "Charts" será cargado por el motor QML, y los tipos proporcionados por ese módulo estarán disponibles para su uso en cualquier documento QML que lo importe.
Capítulo 7: Resumen
En este tutorial, hemos mostrado los pasos básicos para crear una extensión QML:
- Definir nuevos tipos QML subclasificando QObject y registrándolos con QML_ELEMENT o QML_NAMED_ELEMENT()
- Añadir métodos invocables utilizando Q_INVOKABLE o ranuras Qt, y conectarse a las señales Qt con una sintaxis
onSignal - Añada enlaces de propiedades definiendo señales NOTIFY.
- Definir tipos de propiedades personalizados si los tipos incorporados no son suficientes
- Definir tipos de propiedades de lista mediante QQmlListProperty
- Crear una biblioteca de plugins definiendo un plugin Qt y escribiendo un archivo qmldir
La documentación general de Integración de QML y C++ muestra otras características útiles que pueden añadirse a las extensiones QML. Por ejemplo, podríamos usar propiedades por defecto para permitir que se añadan slices sin usar la propiedad slices:
PieChart {
PieSlice { ... }
PieSlice { ... }
PieSlice { ... }
}O añadir y eliminar slices aleatoriamente cada cierto tiempo utilizando fuentes de valores de propiedades:
PieChart {
PieSliceRandomizer on slices {}
}Nota: Para continuar aprendiendo sobre las extensiones y características de QML sigue el tutorial Escribiendo extensiones QML avanzadas con C++.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.