¿Puede la función de ranura de clase C importada a QML tener parámetros? ¿A qué debo prestar atención en comparación con la función de ranura sin parámetros? Pídele a Dios que aclare tus dudas.
1. ¿Por qué necesitamos programación mixta entre QML y C?
¿Por qué necesitamos mezclar programación QML y C? En pocas palabras, QML se utiliza para crear UI de manera eficiente. Y convenientemente, si bien C se utiliza para implementar lógica empresarial y algoritmos complejos, los métodos y técnicas para la interacción entre los dos se presentan a continuación.
2. Descripción general de QML accediendo a C
Qt integra el motor QML y el sistema de metaobjetos Qt, lo que facilita la extensión de QML desde C. Bajo ciertas condiciones, QML Puede acceder a miembros de clases derivadas de QObject, como señales, funciones de ranura, tipos de enumeración, propiedades, funciones miembro, etc.
Hay dos métodos para que QML acceda a C: uno es registrar la clase C en el sistema de metaobjetos Qt y crear una instancia y acceder a ella en QML. El segundo es crear una instancia en C, configurarlo como un atributo de contexto QML y usarlo directamente en QML. En comparación con el último, el primero puede usar la clase C como tipo de datos en QML, como el tipo de parámetro de función o el tipo de atributo, y también puede usar su tipo de enumeración, singleton, etc., que es más poderoso.
3. Cómo implementar una clase C a la que se pueda acceder mediante QML
Si se quiere acceder a una clase C mediante QML, primero debe cumplir dos condiciones: Primero, que sea derivado de la clase QObject o la subclase de la clase QObject, el segundo es usar la macro Q_OBJECT. La clase QObject es la clase base para todos los objetos Qt. Como núcleo del modelo de objetos Qt, proporciona muchas características importantes, como señales y mecanismos de ranura. La macro Q_OBJECT debe declararse en el área privada (C por defecto es privada. Se utiliza para declarar señales y ranuras. Utiliza el contenido proporcionado por el sistema de metaobjetos Qt y generalmente se encuentra en la primera línea del bloque de declaraciones). . El siguiente ejemplo se crea en QtCreator3.1.2, seleccione QtQuickApplication para Proyectos, el nombre del proyecto es Gemini, seleccione QtQuick2.2 para Componente y luego agregue ladrillos y mosaicos al archivo generado automáticamente.
Señales y ranuras——
(1) Agregar el archivo de encabezado Gemini.h
[cpp]?view Plain?copy?
#ifndef?GEMINI_H?
#define?GEMINI_H?
//?Gemini.h?
#include?lt;QObjectgt;? p >
#include?lt;QDebuggt;?
clase?Gemini?:?public?QObject?
{?
Q_OBJECT? p >
señales:?
void?begin();?
ranuras?públicas:?
void?doSomething()?{?< / p>
qDebug()?lt;lt;?"Gemini::doSomething()?llamado";?
}?
};?
#endif?//?GEMINI_H?
QML puede acceder a la señal comenzar() y a la ranura doSomething() en la clase Gemini. La ranura debe declararse como pública o protegida. Cuando se usa la señal en C, se debe usar la palabra clave emit, pero en QML es una función ordinaria. Su uso es el mismo que el de la función. forma de onlt; Signalgt;, y la primera letra de Signal está en mayúscula. Las señales no admiten la sobrecarga. Cuando varias señales tienen el mismo nombre pero diferentes parámetros, solo se puede reconocer la última señal, independientemente de los parámetros de la señal.
(2) Modificar main.cpp[cpp]?view Plain?copy?
//?main.cpp?
#include?lt QGuiApplicationgt; ;?
#include?lt;QQmlApplicationEnginegt;?
#include?lt;QtQmlgt;?
#include?lt;Gemini.hgt;?
int?main(int?argc, ?char?*argv[])?
{?
QGuiApplication?app(argc, ?argv);?
qmlRegisterTypelt;Geminigt;("Union.Lotto.Gemini",?1,?0,?"Gemini");?
QQmlApplicationEngine?engine;?
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));?
return?app.exec();?
}?
Aquí la clase Gemini se registra (qmlRegisterType) en el sistema de metaobjetos Qt. Por supuesto, también se puede crear una instancia primero y luego configurarla como un atributo de contexto QML. El contenido relevante se presentará en detalle. más tarde.
(3) ¿Modificar main.qml[sql]?view Plain?copy?
//?main.qml?
importar?QtQuick?2.2?
¿importar?QtQuick.Window?2.1?
¿importar?Union.Lotto.Gemini?1.0?
¿Ventana?{?
visible:?verdadero?
ancho:?360;?alto:?360?
título:?"Union?Lotto?Game"?
color: ?"blanco"?
MouseArea?{?
anchors.fill: ?parent?
onClicked: ?{?
géminis .begin()?
}?
}?
¿Géminis?{?
id: ?géminis?
onBegin:?doSomething()?
}?
}?
Después de que la clase Gemini esté registrada en el sistema de metaobjetos Qt, y en la importación de archivos QML (importación), la palabra clave Gemini se puede utilizar como tipo QML en el archivo QML actual. En el ejemplo, hay un MouseArea. Cuando se hace clic con el mouse, se envía la señal de inicio () y se llama a la función de ranura doSomething ().
Tipo de enumeración——
(1) Modificar el archivo de encabezado Gemini.h[cpp]?view Plain?copy?
#ifndef?GEMINI_H?
#define?GEMINI_H?
//?Gemini.h?
#include?lt;QObjectgt;?
#include? lt; QDebuggt;?
¿clase?Géminis?:?público?QObject?
{?
Q_OBJECT?
Q_ENUMS(BALL_COLOR) )?
público:?
Géminis()?:?m_ballColor(BALL_COLOR_YELLOW)?{?
qDebug()?lt;lt;?"Géminis :: Géminis()?llamado";?
}?
enum?BALL_COLOR?{?
BALL_COLOR_YELLOW,?
BALL_COLOR_RED ,?
BALL_COLOR_BLUE,?
BALL_COLOR_ALL?
};?
señales:?
¿vacío? comenzar();?
ranuras públicas:?
void?doSomething(BALL_COLOR?ballColor)?{?
qDebug()?lt;lt; ?"Géminis::hacerAlgo()?llamado?con"?lt;lt;?ballColor;?
if(ballColor?!=?m_ballColor)?{?
m_ballColor? =?ballColor;?
qDebug()?lt;lt;?"ball?color?changed";?
}?
}? p>
privado:?
BALL_COLOR?m_ballColor;?
};?
#endif?//?GEMINI_H?
El tipo de enumeración pública BALL_COLOR se ha agregado a la clase Gemini. Si este tipo de enumeración se va a utilizar en QML, se utiliza la macro Q_ENUMS().
(2) ¿Modificar main.qml[plain]?view Plain?copy?
//?main.qml?
importar?QtQuick?2.2?
¿importar?QtQuick.Window?2.1?
¿importar?Union.Lotto.Gemini?1.0?
¿Ventana?{?
visible:?verdadero?
ancho:?360;?alto:?360?
título:?"Union?Lotto?Game"?
color: ?"blanco"?
MouseArea?{?
anchors.fill: ?parent?
onClicked: ?{?
géminis .begin()?
}?
}?
¿Géminis?{?
id: ?géminis?
onBegin:?doSomething(Gemini.BALL_COLOR_RED)?
}?
}?
La forma de utilizar tipos de enumeración en QML es lt; ;.lt;ENUM_VALUEgt;, como Gemini.BALL_COLOR_RED.
Función miembro——
(1) Modificar el archivo de encabezado Gemini.h[cpp]?view Plain?copy?
#ifndef?GEMINI_H?< / p>
#define?GEMINI_H?
//?Gemini.h?
#include?lt;QObjectgt;?
#include? lt ;QDebuggt;?
clase?Gemini?:?public?QObject?
{?
Q_OBJECT?
Q_ENUMS(BALL_COLOR ) ?
público:?
Géminis()?:?m_ballColor(BALL_COLOR_YELLOW)?{?
qDebug()?lt;lt;?"Géminis : : Géminis()?llamado";?
}?
enum?BALL_COLOR?{?
BALL_COLOR_YELLOW,?
BALL_COLOR_RED , ?
BALL_COLOR_BLUE,?
BALL_COLOR_ALL?
};?
Q_INVOKABLE?void?stop()?{? p >
qDebug()?lt;lt;?"Gemini::stop()?llamado";?
}?
señales:?
void?begin();?
public?slots:?
void?doSomething(BALL_COLOR?ballColor)?{?
qDebug()? lt ;lt;?"Gemini::doSomething()?llamado?con"?lt;lt;?ballColor;?
if(ballColor?!=?m_ballColor)?{?
m_ballColor?=?ballColor;?
qDebug()?lt;lt;?"ball?color?changed";?
}?
} ?
privado:?
BALL_COLOR?m_ballColor;?
};?
#endif?//?GEMINI_H?< / p>
La función miembro stop() se ha agregado a la clase Gemini. El requisito previo para el acceso en QML es una función miembro pública o protegida, se utiliza la macro Q_INVOKABLE y la posición está delante de la función. tipo de devolución.
(2) ¿Modificar main.qml[plain]?view Plain?copy?
//?main.qml?
importar?QtQuick?2.2?
¿importar?QtQuick.Window?2.1?
¿importar?Union.Lotto.Gemini?1.0?
¿Ventana?{?
visible:?verdadero?
ancho:?360;?alto:?360?
título:?"Union?Lotto?Game"?
color: ?"blanco"?
MouseArea?{?
anchors.fill: ?parent?
onClicked: ?{?
géminis .begin()?
géminis.stop()?
}?
}?
Géminis?{?
id: ?gemini?
onBegin: ?doSomething(Gemini.BALL_COLOR_RED)?
}?
}?
La forma de acceder a las funciones miembro de C en QML es lt;idgt;.lt;methodgt;, como gemini.stop(). Admite la sobrecarga de funciones, que es diferente de las señales.
Atributos de la clase C——
(1) Modificar el archivo de encabezado Gemini.h[cpp]?view Plain?copy?
#ifndef?GEMINI_H
#define?GEMINI_H?
//?Gemini.h?
#include?lt;QObjectgt;?
#? incluir ?lt QDebuggt;?
clase?Géminis?:?público?QObject?
{?
Q_OBJECT?
Q_ENUMS ( BALL_COLOR)?
Q_PROPERTY(unsigned?int?ballNumber?READ?ballNumber?WRITE?setBallNumber?NOTIFY?ballNumberChanged)?
público:?
Géminis ( )?:?m_ballColor(BALL_COLOR_YELLOW),?m_ballNumber(0)?{?
qDebug()?lt;lt;?"Gemini::Gemini()?llamado";?
}?
enum?BALL_COLOR?{?
BALL_COLOR_YELLOW,?
BALL_COLOR_RED,?
BALL_COLOR_BLUE,? p >
BALL_COLOR_ALL?
};?
unsigned?int?ballNumber()?const?{?
return?m_ballNumber;? p >
}?
void?setBallNumber(const?unsigned?int?amp; ballNumber)?{?
if(ballNumber?!=?m_ballNumber)?{?
m_ballNumber?=?ballNumber;?
emitir?ballNumberChanged();?
}?
}?
Q_INVOKABLE?void?stop()?{?
qDebug()?lt;lt;?"Gemini::stop()?Call";?
}?
señales:?
void?begin();?
void?ballNumberChanged();?
¿ranuras?públicas:?
void?doSomething(BALL_COLOR?ballColor)?{?
qDebug()?lt;lt;?"Gemini::doSomething()?llamado?with"?lt;lt ?ballColor;?
if(ballColor?!=?m_ballColor)?{?
m_ballColor?=?ballColor;?
qDebug()?lt ; lt;?"bola?color?cambiado";?
}?
}?
privado:?
BALL_COLOR? m_ballCol
o;?
unsigned?int?m_ballNumber;?
};?
#endif?//?GEMINI_H?
Géminis La macro Q_PROPERTY() se ha agregado a la clase para declarar propiedades en clases derivadas de QObject. Esta propiedad es como un miembro de datos de la clase, pero tiene algunas características adicionales a las que se puede acceder a través del sistema de metaobjetos Qt.
El siguiente es el prototipo de la macro Q_PROPERTY(): [cpp]?ver plano?copiar?
Q_PROPERTY()(tipo?nombre?
(¿LEER? getFunction?[WRITE?setFunction]?|?
¿MIEMBRO?memberName?[(LEER?getFunction?|?WRITE?setFunction)])?
[RESET?resetFunction ]?
[NOTIFY?notifySignal]?
[REVISIÓN?int]?
[DESIGNABLE?bool]?
[SCRIPTABLE ?bool] ?
[ALMACENADO?bool]?
[USUARIO?bool]?
[CONSTANTE]?
[FINAL ])?
El tipo y nombre de los atributos son obligatorios, y los demás son opcionales. Los más utilizados incluyen LEER, ESCRIBIR y NOTIFICAR. El tipo de atributo puede ser cualquier tipo admitido por QVariant, o puede ser un tipo personalizado, incluidas clases personalizadas, tipos de listas, atributos de grupo, etc. Además, los atributos LEER, ESCRIBIR y RESET pueden ser funciones heredadas o virtuales. Estas características no se utilizan comúnmente.
LEER: Lee el valor del atributo, es obligatorio si MIEMBRO no está configurado. En general, la función es una función constante y el tipo de valor de retorno debe ser el tipo del atributo en sí o una referencia constante de este tipo, sin parámetros.
ESCRIBIR: Establecer valor de atributo, opcional. La función debe devolver void y tener un solo parámetro. El tipo de parámetro debe ser el tipo del atributo en sí o un puntero o referencia de este tipo.
NOTIFICAR: Señal opcional asociada a la propiedad. Esta señal debe declararse en la clase. Cuando el valor del atributo cambia, esta señal se puede activar. No necesita parámetros. Si hay un parámetro, solo puede ser un parámetro del mismo tipo que el atributo en sí. Se utiliza para registrar el valor modificado del atributo.
Para conocer el uso detallado de Q_PROPERTY(), consulte el siguiente sitio web:
(2) Modificar main.qml[sql]?view Plain?copy?
// ?main.qml?
¿importar?QtQuick?2.2?
¿importar?QtQuick.Window?2.1?
importar?Union.Lotto. Géminis?1.0?
¿Ventana?{?
visible:?verdadero?
ancho:?360;?alto:?360?
título: ?"¿Unión?¿Lotería?Juego"?
color:?"blanco"?
Área del ratón?{?
anclajes.relleno:? ¿padre? p>
onClicked:?{?
gemini.begin()?
gemini.stop()?
gemini.ballNumber ?=?10 ?
}?
}?
Géminis?{?
id: ?géminis?
onBegin :?doSomething(Gemini.BALL_COLOR_RED)?
onBallNumberChanged:?console.log("new?ball?number?is",?ballNumber)?/?10?
Componente .onCompleted:?console.log("default?ball?number?is",?ballNumber)?//?0?
}?
}?
Se puede acceder y modificar el atributo ballNumber en la clase Gemini en QML. Al acceder, se llama a la función ballNumber () y al modificar, se llama a la función setBallNumber (). enviado para actualizar automáticamente el valor del atributo.
4. Registrar la clase C como tipo QML
La clase derivada de QObject se puede registrar en el sistema de metaobjetos Qt, de modo que la clase se pueda usar como datos en QML como otros. tipos incorporados. El motor QML permite el registro de tipos instanciables y no instanciables. Las funciones de registro comunes son: [cpp]?view Plain?copy?
qmlRegisterInterface()?
qmlRegisterRevision()?
qmlRegisterSingletonType()?
qmlRegisterType()?
qmlRegisterTypeNotAvailable()?
qmlRegisterUncreatableType()? > Cada una de estas funciones de registro tiene sus propios usos y se pueden seleccionar según las necesidades reales. Al usarlas, debe incluir ltQtQmlgt;.
El más utilizado es qmlRegisterType(), que tiene tres funciones sobrecargadas. Aquí solo se presenta una de ellas: [cpp]?view Plain?copy?
templatelt;
int?qmlRegisterType(const?char?*uri,?
int?versionMajor,?
int?versionMinor,
const?char?* qmlName); ?
Esta función de plantilla registra la clase C en el sistema de metaobjetos Qt. uri es el nombre de la biblioteca que debe importarse a QML y versionMinor son sus números de versión. escriba el nombre que se puede utilizar en QML. Por ejemplo, el código en main.cpp en el ejemplo anterior: [cpp]?view Plain?copy?
qmlRegisterTypelt; ("Union.Lotto.Gemini",?1,?0,? "Géminis" );