Compilador de tipos QML
El compilador de tipos QML, qmltc, es una herramienta incluida con Qt para traducir tipos QML a tipos C++ que se compilan antes de tiempo como parte del código de usuario. El uso de qmltc puede mejorar el rendimiento en tiempo de ejecución debido a las mayores oportunidades de optimización de que dispone el compilador en comparación con la creación de objetos basada en QQmlComponent. qmltc forma parte de la cadena de herramientas del compiladorQt Quick .
Por su diseño, qmltc genera código orientado al usuario. Ese código se supone que debe ser utilizado por la aplicación C++ directamente, de lo contrario no verá ningún beneficio. Este código generado sustituye esencialmente a QQmlComponent y sus API para crear objetos a partir de documentos QML. Puedes encontrar más información en Uso de qmltc en una aplicación QML y Fundamentos de la salida generada.
Para habilitar qmltc:
- Cree un módulo QML adecuado para su aplicación.
- Invoque qmltc, por ejemplo, a través de la API CMake.
#includeel(los) archivo(s) de cabecera generado(s) en el código fuente de la aplicación.- Instanciar un objeto del tipo generado.
En este flujo de trabajo, qmltc suele ejecutarse durante el proceso de compilación. Por lo tanto, cuando qmltc rechaza un documento QML (ya sea debido a errores o advertencias, o debido a construcciones qmltc aún no admite), el proceso de construcción fallará. Esto es similar a cómo se reciben errores de qmllint cuando se habilita la generación automática de objetivos de linting durante la creación de módulos QML y luego se intenta "construirlos" para ejecutar el qmllint.
Advertencia: qmltc se encuentra actualmente en una fase de Tech Preview y podría no compilar un programa QML arbitrario (consulte Limitaciones conocidas para obtener más detalles). Cuando qmltc falla, no se genera nada, ya que su aplicación no puede utilizar con sentido la salida de qmltc. Si su programa contiene errores (o advertencias irresolubles), deben ser corregidos para permitir la compilación. La regla general es adherirse a las mejores prácticas y seguir los consejos de qmllint.
Nota: qmltc no garantiza que el C++ generado siga siendo compatible con la API, el código fuente o el binario entre versiones pasadas o futuras, incluso versiones de parches. Además, las aplicaciones compiladas con qmltc que utilicen módulos QML de Qt necesitarán enlazarse con la API privada de Qt. Esto se debe a que los módulos QML de Qt no suelen proporcionar una API C++ pública, ya que su uso principal es a través de QML.
Uso de qmltc en una aplicación QML
Desde la perspectiva del sistema de compilación, añadir la compilación qmltc no es muy diferente de añadir la generación de caché qml. Ingenuamente, el proceso de compilación podría describirse como:

Aunque el proceso de compilación real es mucho más complicado, este diagrama captura los componentes principales que utiliza qmltc: los propios archivos QML y qmldir con la información qmltypes. Las aplicaciones más sencillas suelen tener un qmldir bastante primitivo pero, en general, qmldir puede ser complejo, ya que proporciona información de tipos esencial y bien empaquetada en la que qmltc confía para realizar una traducción correcta de QML a C++.
No obstante, en el caso de qmltc no basta con añadir un paso de compilación adicional. El código de la aplicación también debe modificarse para utilizar clases generadas por qmltc en lugar de QQmlComponent o sus alternativas de nivel superior.
Compilación de código QML con qmltc
Qt, a partir de Qt 6, utiliza CMake para construir sus diversos componentes. Los proyectos de usuario pueden - y se les anima a - utilizar también CMake para construir sus componentes utilizando Qt. Añadir soporte de compilación qmltc a tu proyecto requeriría un flujo de compilación basado en CMake, ya que este flujo está centrado en módulos QML y su infraestructura.
La forma más sencilla de añadir la compilación qmltc es utilizando la API CMake dedicada como parte de la creación de un módulo QML para la aplicación. Considere una estructura de directorios de aplicación simple:
. ├── CMakeLists.txt ├── myspecialtype.h // C++ type exposed to QML ├── myspecialtype.cpp ├── myApp.qml // main QML page ├── MyButton.qml // custom UI button ├── MySlider.qml // custom UI slider └── main.cpp // main C++ application file
Entonces el código CMake normalmente se vería similar a la siguiente:
# Use "my_qmltc_example" as an application name:
set(application_name my_qmltc_example)
# Create a CMake target, add C++ source files, link libraries, etc...
# Specify a list of QML files to be compiled:
set(application_qml_files
myApp.qml
MyButton.qml
MySlider.qml
)
# Make the application into a proper QML module:
qt6_add_qml_module(${application_name}
URI QmltcExample
QML_FILES ${application_qml_files}
# Compile qml files (listed in QML_FILES) to C++ using qmltc and add these
# files to the application binary:
ENABLE_TYPE_COMPILER
NO_GENERATE_EXTRA_QMLDIRS
)
# (qmltc-specific) Link *private* libraries that correspond to QML modules:
find_package(Qt6 COMPONENTS QmlPrivate QuickPrivate)
target_link_libraries(${application_name} PRIVATE Qt::QmlPrivate Qt::QuickPrivate)Uso del C++ generado
A diferencia del caso de la instanciación de QQmlComponent, la salida de qmltc, al ser código C++, es utilizada directamente por la aplicación. Generalmente, construir un nuevo objeto en C++ es equivalente a crear un nuevo objeto a través de QQmlComponent::create(). Una vez creado, el objeto podría ser manipulado desde C++ o, por ejemplo, combinado con QQuickWindow para ser dibujado en pantalla.
Si un tipo compilado expone algunas propiedades requeridas, `qmltc` requerirá un valor inicial para esas propiedades en el constructor para el objeto generado.
Además, el constructor de un objeto qmltc puede incluir una llamada de retorno para establecer los valores iniciales de las propiedades del componente.
Dado un archivo myApp.qml, el código de la aplicación (en ambos casos) tendría normalmente este aspecto:
#include <QtQml/qqmlcomponent.h> QGuiApplication app(argc, argv); app.setApplicationDisplayName(QStringLiteral("This example is powered by QQmlComponent :(")); QQmlEngine e; // If the root element is Window, you don't need to create a Window. // The snippet is for the cases where the root element is not a Window. QQuickWindow window; QQmlComponent component(&e); component.loadUrl( QUrl(QStringLiteral("qrc:/qt/qml/QmltcExample/myApp.qml"))); QScopedPointer<QObject> documentRoot(component.create()); QQuickItem *documentRootItem = qobject_cast<QQuickItem *>(documentRoot.get()); documentRootItem->setParentItem(window.contentItem()); window.setHeight(documentRootItem->height()); window.setWidth(documentRootItem->width()); // ... window.show(); app.exec();
#include "myapp.h" // include generated C++ header QGuiApplication app(argc, argv); app.setApplicationDisplayName(QStringLiteral("This example is powered by qmltc!")); QQmlEngine e; // If the root element is Window, you don't need to create a Window. // The snippet is for the cases where the root element is not a Window. QQuickWindow window; QScopedPointer<QmltcExample::myApp> documentRoot( new QmltcExample::myApp(&e, nullptr, [](auto& component){ component.setWidth(800); })); documentRoot->setParentItem(window.contentItem()); window.setHeight(documentRoot->height()); window.setWidth(documentRoot->width()); // ... window.show(); app.exec();
Motor QML
El código generado utiliza QQmlEngine para interactuar con las partes dinámicas de un documento QML, principalmente el código JavaScript. Para que esto funcione, no se necesitan arreglos especiales. Cualquier instancia de QQmlEngine pasada al constructor de un objeto de clase generado por qmltc debería funcionar correctamente, al igual que QQmlComponent(engine). Esto también significa que puede utilizar QQmlEngine methods que afectan al comportamiento de QML. Sin embargo, hay algunas advertencias. A diferencia de la creación de objetos basada en QQmlComponent, qmltc no se basa en QQmlEngine al compilar el código en C++. Por ejemplo, QQmlEngine::addImportPath("/foo/bar/") - que normalmente resulta en una ruta de importación adicional a buscar - sería completamente ignorada por el procedimiento qmltc anticipado.
Nota: Para añadir rutas de importación a la compilación qmltc, considere usar un argumento relevante del comando CMake en su lugar.
En general, se puede pensar de esta manera: QQmlEngine implica que el proceso de aplicación se ejecute, mientras que qmltc no lo hace, ya que opera incluso antes de que tu aplicación se compile. Dado que qmltc no hace ningún intento de introspección del código fuente C++ de tu aplicación, no hay forma de que conozca ciertos tipos de manipulaciones QML que tú, como usuario, haces. En lugar de utilizar QQmlEngine y las rutinas de ejecución relacionadas para exponer tipos a QML, añadiendo rutas de importación, etc., prácticamente se requiere crear módulos QML que se comporten bien y utilizar el registro declarativo de tipos QML.
Advertencia: A pesar de que qmltc trabaja estrechamente con QQmlEngine y crea código C++, las clases generadas no pueden ser expuestas a QML y utilizadas a través de QQmlComponent.
Aspectos básicos de la salida generada
qmltc pretende ser compatible con el modelo de ejecución QML existente. Esto implica que el código generado es aproximadamente equivalente a la lógica de configuración interna de QQmlComponent y, por tanto, debería poder comprender el comportamiento, la semántica y la API de su tipo QML del mismo modo que lo hace actualmente: inspeccionando visualmente el documento QML correspondiente.
Sin embargo, el código generado sigue siendo algo confuso, sobre todo teniendo en cuenta que su aplicación debe utilizar la salida qmltc en el lado C++ directamente. Hay dos partes del código generado: CMake estructura de archivos de construcción y el formato generado C ++. El primero está cubierto en el CMake API de qmltc y el segundo está cubierto aquí.
Consideremos un simple tipo HelloWorld, que tiene una propiedad hello, una función para imprimir esa propiedad, y una señal emitida cuando se crea el objeto de ese tipo:
// HelloWorld.qml import QtQml QtObject { id: me property string hello: "Hello, qmltc!" function printHello(prefix: string, suffix: string) { console.log(prefix + me.hello + suffix); } signal created() Component.onCompleted: me.created(); }
Al proporcionar una alternativa C++ de este tipo QML, la clase C++ necesitaría una macro de sistema meta-objeto específica de QML, una decoración Q_PROPERTY para la propiedad hello, una función de impresión Q_INVOKABLE C++ y una definición de señal Qt normal. Del mismo modo, qmltc traduciría el tipo HelloWorld dado en aproximadamente lo siguiente:
class HelloWorld : public QObject { Q_OBJECT QML_ELEMENT Q_PROPERTY(QString hello READ hello WRITE setHello BINDABLE bindableHello) public: HelloWorld(QQmlEngine* engine, QObject* parent = nullptr, [[maybe_unused]] qxp::function_ref<void(PropertyInitializer&)> initializer = [](PropertyInitializer&){}); Q_SIGNALS: void created(); public: QString hello(); void setHello(const QString& hello_); QBindable<QString> bindableHello(); Q_INVOKABLE void printHello(passByConstRefOrValue<QString> prefix, passByConstRefOrValue<QString> suffix); // ... };
Aunque los detalles específicos del tipo generado podrían diferir, los aspectos universales permanecen. Por ejemplo:
- Los tipos QML dentro de un documento se traducen a tipos C++, de acuerdo con la información visible para el compilador.
- Las propiedades se traducen a propiedades C++ con declaraciones Q_PROPERTY.
- Las funciones JavaScript se convierten en funciones C++
Q_INVOKABLE. - Las señales QML se transforman en señales Qt C++.
- Las enumeraciones QML se convierten en enumeraciones C++ con declaraciones
Q_ENUM.
Un detalle adicional es la forma en que qmltc genera los nombres de las clases. Un nombre de clase para un tipo QML dado se deduce automáticamente del documento QML que define ese tipo: el nombre de archivo QML sin extensiones (hasta y excluyendo el primer ., también conocido como nombre base) se convierte en un nombre de clase. El nombre de archivo conserva las mayúsculas y minúsculas. Así, HelloWorld.qml daría lugar a class HelloWorld y helloWoRlD.qml a class helloWoRlD. Siguiendo la convención de QML, si el nombre de archivo de un documento QML empieza por una letra minúscula, se asume que la clase C++ generada es anónima y se marca con QML_ANONYMOUS.
Por ahora, aunque el código generado está listo para ser utilizado desde el lado de la aplicación C++, en general deberías limitar las llamadas a las APIs generadas. En su lugar, prefiera implementar la lógica de la aplicación en QML/JavaScript y escribir a mano los tipos C++ expuestos a QML, utilizando las clases creadas por qmltc para la instanciación simple de objetos. Aunque el C++ generado le proporciona acceso directo (y normalmente más rápido) a los elementos del tipo definidos por QML, la comprensión de dicho código podría suponer un reto.
Limitaciones conocidas
A pesar de cubrir muchas características comunes de QML, qmltc está todavía en una fase temprana de desarrollo con algunas cosas aún por soportar.
Los módulos QML importados que consisten en tipos definidos por QML (como QtQuick.Controls) podrían no compilarse correctamente, incluso si esos tipos definidos por QML fueron compilados por qmltc.. En la actualidad, puede utilizar de forma fiable los módulos QtQml y QtQuick, así como cualquier otro módulo QML que sólo contenga clases C++ expuestas a QML.
Además de esto, hay que tener en cuenta algunas peculiaridades más fundamentales:
- Los módulos QML de Qt suelen depender de bibliotecas C++ para hacer el trabajo pesado. A menudo, estas bibliotecas no proporcionan una API C++ pública (ya que su uso principal es a través de QML). Para los usuarios de qmltc, esto significa que sus aplicaciones necesitan enlazar con bibliotecas Qt privadas.
- Debido a la naturaleza de la generación de código qmltc, los plugins QML son inutilizables a efectos de compilación. En su lugar, los módulos QML - que utilizan un plugin - tienen que asegurarse de que los datos del plugin son accesibles en tiempo de compilación. Dichos módulos QML tendrían entonces plugins opcionales. En la mayoría de los casos, la información en tiempo de compilación puede proporcionarse a través de un archivo de cabecera (con declaraciones C++) y una biblioteca enlazable (con definiciones C++). El código de usuario es responsable (normalmente a través de CMake) de incluir una ruta al archivo de cabecera y de enlazar con la biblioteca de módulos QML.
Nota: Dado el estado de previsualización técnica del compilador, es posible que encuentres errores en qmltc, en el código generado o en alguna otra parte relacionada. Te animamos a que envíes un informe de errores en este caso.
© 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.