Para crear una lista desplegable en Qt Quick, usaremos el componente ComboBox
. Cuando ejecutes esta aplicación, verás un ComboBox
que despliega la lista de elementos. Al seleccionar un elemento, se mostrará en la parte superior del ComboBox
, y se imprimirá en la consola el elemento seleccionado.
import QtQuick
import QtQuick.Controls
ApplicationWindow {
visible: true
width: 400
height: 200
title: "Lista Desplegable"
ComboBox {
id: comboBox
width: parent.width - 20
model: ListModel {
ListElement { text: "Elemento 1" }
ListElement { text: "Elemento 2" }
ListElement { text: "Elemento 3" }
}
onCurrentIndexChanged: {
var selectedText = model.get(currentIndex).text;
console.log("Seleccionaste: " + selectedText);
}
}
}
En este ejemplo, hemos utilizado un ComboBox
que muestra una lista de elementos desplegables. Los elementos se definen en un modelo, y cuando seleccionas un elemento en el ComboBox
, se ejecuta la función onCurrentIndexChanged
, que imprime el elemento seleccionado en la consola.
Un ejemplo más elaborado: Crear, copiar los códigos y ejecutar el proyecto que contiene los 3 archivos siguientes: myObject.h, main.cpp y Main.qml:
myObject.h
// MyObject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QObject>
#include <QQmlContext>
#include <QtQml>
class MyObject : public QObject
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(int new_generateNumber MEMBER my_generateNumber NOTIFY generateNumber_slot);
public:
explicit MyObject(QObject *parent = nullptr);
Q_INVOKABLE void generateNumber(int min, int max);
Q_INVOKABLE int getX();
public slots:
void generateNumber_slot();
signals:
void generateNumber_signal(int);
private:
int my_generateNumber = 0;
};
#endif // MYOBJECT_H
Aquí está una descripción de las principales líneas del código anterior:
- Inclusión de cabeceras: El código incluye varias cabeceras de Qt, como
QObject
,QQmlContext
,QtQml
, que son necesarias para trabajar con Qt Quick y para la creación de objetos QML. - Declaración de la clase
MyObject
: La clase creadaMyObject
se deriva deQObject
, lo que la hace una clase que puede ser utilizada en el sistema de objetos de Qt. Además, se marca con la macroQ_OBJECT
, que es necesaria para habilitar la funcionalidad de señales y ranuras de Qt. - Uso de la macro
QML_ELEMENT
: Esta macro se usa para registrar la clase como un elemento QML, lo que permite su uso en archivos QML. - Declaración de una propiedad QML: Se declara una propiedad llamada
new_generateNumber
que se conecta al miembromy_generateNumber
. Esto permitirá a los objetos QML acceder y modificar el valor demy_generateNumber
a través de esta propiedad. - Métodos Q_INVOKABLE: Se declaran dos métodos marcados como
Q_INVOKABLE
. Estos métodos pueden ser llamados desde el código QML.generateNumber
toma dos parámetros (min y max) ygetX
no toma ningún parámetro.generateNumber_slot
es un método público que se puede invocar desde fuera de la clase. - Signals y slots: Se declara una señal llamada
generateNumber_signal
que emite un entero como argumento. También hay un slot llamadogenerateNumber_slot
. Las señales y los slots se utilizan para la comunicación entre objetos en Qt.
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QDebug>
#include <QRandomGenerator>
#include "MyObject.h"
// Funciones para manejar las señales
MyObject::MyObject(QObject *parent)
: QObject(parent)
{
QObject::connect(this, &MyObject::generateNumber_signal, this, &MyObject::generateNumber_slot);
}
void MyObject::generateNumber_slot(){
my_generateNumber++;
qInfo() << "Dentro de slot:" << my_generateNumber;
}
int MyObject::getX()
{
return 10;
}
QStringList getList()
{
QStringList dataList = {
"Item A",
"Item B",
"Item C",
"Item D"
};
return dataList;
}
void MyObject::generateNumber(int min, int max)
{
const int num_aleatorio = QRandomGenerator::global()->bounded(min,max);
qDebug() << "Called the c++ signal with num_aleatorio" << num_aleatorio;
emit generateNumber_signal(num_aleatorio);
}
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(u"qrc:/MiProyectoQtQuick_1/Main.qml"_qs);
engine.load(url);
if (engine.rootObjects().isEmpty())
return -1;
engine.rootContext()->setContextProperty("comboModel2", getList() );
return app.exec();
}
Este código anterior es la implementación principal de la aplicación en C++ que utiliza Qt y Qt Quick para crear una interfaz de usuario y conectarla con la clase MyObject
que hemos definido previamente:
- Incluye las cabeceras necesarias, como
QGuiApplication
,QQmlApplicationEngine
,QQmlContext
,QDebug
,QRandomGenerator
y el archivo de cabecera"MyObject.h"
, que contiene la definición de la claseMyObject
. - En la función
main
, se crea una instancia deQGuiApplication
para manejar la aplicación y una instancia deQQmlApplicationEngine
para cargar y ejecutar la interfaz de usuario QML. - Se carga el archivo QML principal (
Main.qml
) desde un recurso Qt utilizando la URLqrc:/MiProyectoQtQuick_1/Main.qml
. - Si la carga del motor de aplicaciones QML tiene éxito, se establece el contexto de la raíz del motor para exponer un modelo de datos (
comboModel2
) al QML. En este caso, el modelo de datos es una lista de cadenas obtenidas de la funcióngetList()
. - Se ejecuta la aplicación llamando a
app.exec()
, lo que inicia el bucle principal de la aplicación y muestra la ventana de la interfaz de usuario. - En el código de la clase
MyObject
, se definen las funciones que se conectan a señales y se pueden llamar desde QML. La funcióngenerateNumber_slot
se conecta a la señalgenerateNumber_signal
, y cuando se emite esta señal, incrementa el valor demy_generateNumber
y muestra un mensaje de registro con el nuevo valor. La funcióngetX
simplemente devuelve el valor 10. - La función
generateNumber
genera un número aleatorio entre los valoresmin
ymax
, emite la señalgenerateNumber_signal
con ese número y muestra un mensaje de registro con el número aleatorio generado.
Main.qml
import QtQuick 2.3
import QtQuick.Controls 2.2
import QtQuick.Layouts
import QtQuick.Controls.Material
import MiProyectoQtQuick_1
ApplicationWindow {
id: window1
visible: true
width: 640
height: 480
title: qsTr("App: " + windowTitle)
property string windowTitle: "Hola Mundo"
property int randNum:0
MyObject {
id: myObject
onGenerateNumber_signal: (num) => {
randNum = num
}
}
ComboBox {
id: comboBox1
x: 258
y: 50
model: comboModel
onActivated: {
console.log("ComboBox activated:" + comboBox1.currentIndex)
}
}
ComboBox {
id: comboBox2
currentIndex: 0
model: comboModel2
x: 258
y: 120
}
ListModel {
id: comboModel
ListElement { text: "Item 1" }
ListElement { text: "Item 2" }
ListElement { text: "Item 3" }
}
Button {
id: button1
x: 258
y: 200
text: qsTr("Remove Item de ComboBox1")
onClicked: comboModel.remove(comboBox1.currentIndex)
}
Button {
id: button2
x: 258
y: 250
text: qsTr("Add Item al ComboBox1")
onClicked: comboModel.insert(0, { text: "Nuevo Item" })
}
Button {
id: button3
x: 258
y: 300
text: qsTr("Add Item desde Función C++")
onClicked: {
onClicked: comboModel.insert(0, { text: myObject.getX().toString() })
console.log(" X=" + myObject.getX())
}
}
Button {
id: button4
x: 258
y: 350
text: qsTr("Add Item desde Signal C++")
onClicked: {
myObject.generateNumber(1, 5)
onClicked: comboModel.insert(0, { text: randNum.toString() })
}
}
Button {
id: button5
x: 258
y: 400
text: qsTr("Add Item desde Slot C++")
onClicked: {
myObject.new_generateNumber++
onClicked: comboModel.insert(0, { text: myObject.new_generateNumber.toString() })
}
}
}
El código anterior es una interfaz de usuario en QML que utiliza el objeto MyObject
que hemos definido previamente en C++.
- Importaciones: Se importan varios módulos de Qt Quick y Qt Quick Controls que se utilizarán en la interfaz de usuario. Además, se importa un módulo llamado
MiProyectoQtQuick_1
, que contiene la definición de la claseMyObject
que creamos. ApplicationWindow
: Se crea una ventana de la aplicación (ApplicationWindow
) con propiedades comowidth
,height
,title
, etc. Se define una propiedadwindowTitle
que se utiliza como título de la ventana y una propiedadrandNum
que se utiliza para almacenar un número generado desde el objetoMyObject
.MyObject
: Se crea una instancia de la claseMyObject
con el idmyObject
. Cuando la señalgenerateNumber_signal
demyObject
se emite, se actualiza la propiedadrandNum
con el valor emitido.ComboBox
: Se crean dos listas despegables (ComboBox
) concomboBox1
ycomboBox2
.comboBox1
utiliza un modelo llamadocomboModel
que contiene elementos de lista.comboBox2
utiliza un modelo llamadocomboModel2
.ListModel
: Se define un modelo llamadocomboModel
que contiene elementos de lista (ListElement
) con texto, que se utilizarán encomboBox1
. Este modelo se inicializa con tres elementos.- Botones: Se crean cinco botones con etiquetas y funciones asociadas:
button1
: Elimina el elemento seleccionado encomboBox1
.button2
: Inserta un nuevo elemento al principio decomboBox1
.button3
: Llama a la funcióngetX
demyObject
para obtener un valor desde C++ y lo inserta al principio decomboBox1
.button4
: Llama al métodogenerateNumber
demyObject
para generar un número y lo inserta al principio decomboBox1
.button5
: Incrementa la propiedadnew_generateNumber
demyObject
y lo inserta al principio decomboBox1
.