Bienvenidos sean a este post, hoy veremos ejemplos mas reales de Qt.
Si vienen de los posts anteriores, hemos visto varios ejemplos para explicar algunos conceptos de Qt. En todos los conceptos siempre que trabajamos con mas de un elemento, estos eran independientes uno del otro. Esto es asi porque debe haber un elemento padre para controlarlos a todos, cuando no es asi cada uno es tratado como un elemento de nivel top o padre. Para entender el concepto, vamos a analizar una serie de ejemplos y para ello vamos a ver el mas basico:
#include <QtWidgets>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QWidget ventana;
ventana.resize(400, 100);
ventana.setWindowTitle("Aprendiendo C++ con Tinchicus.com");
ventana.show();
return app.exec();
}
Este codigo genera la aplicacion base que mostraremos en el escritorio, app, y una ventana vacia con un titulo. Como dijimos, esta es el layout inicial de nuestra aplicacion. Modifiquemos el codigo de la siguiente manera para agregar nuestro primero elemento o widget:
#include <QtWidgets>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QWidget ventana;
ventana.resize(400, 100);
ventana.setWindowTitle("Aprendiendo C++ con Tinchicus.com");
QPushButton* btn = new QPushButton("Aprietame", &ventana);
btn->resize(400,30);
ventana.show();
return app.exec();
}
Antes de mostrar la ventana que ahora actuara de padre, agregamos un nuevo elemento que sera un boton. Para ello, usamos a la clase QPushButton y en el constructor primero pasamos el texto que mostrara y el elemento que lo contendra, para nuestro caso la ventana. Luego tomamos ese elemento y la aplicamos el metodo resize para modificar su tamaño. El resto sigue siendo exactamente lo mismo. Con esta nueva modificacion ya podemos pasar a compilarlo. Recuerden que necesitan un archivo con extension .pro, sino lo poseen deben generarlo y para este codigo debe contener lo siguiente:
QT += widgets
SOURCES += qt.cpp
La primer linea es para indicar que modulos de Qt usaremos en nuestro codigo, aqui solamente este, y la siguiente es el codigo fuente que usaremos, y al igual que el caso anterior solamente pasamos al codigo fuente porque es el unico a usar. Si quieren conocer un poco mas sobre esto, les recomiendo este post. Con nuestro archivo creado, lo siguiente es la metacompilacion y para ello deben usar el siguiente comando:
$ qmake6 qt.pro
Este es el metacompilador para la version 6 pero para versiones anteriores es solamente qmake, y en ambos casos le pasamos el archivo .pro generado anteriormente. Esto genera un Makefile, entonces simplemente debemos ejecutar lo siguiente:
$ make
Esto comenzara el proceso de compilacion del codigo para nuestro S.O, una vez finalizado nos creara un archivo ejecutable que una vez ejecutado nos mostrara la siguiente ventana:

En algunos posts anteriores, hubieramos tenido dos elementos separados flotando en pantalla pero ahora tenemos uno conteniendo al otro. Esto es lo mas basico para trabajar con una ventana y elementos pero se puede expandir aun mas.
En el ejemplo tenemos dos elementos, uno para la ventana que es de tipo QWidget y otro de tipo QPushButton que es heredero de QWidget. El primero es el encargado de renderizar la ventana que contendra los elementos, y el boton al ser heredero de esta clase permite que pueda ser manejado por esta. Por esta razon, vamos a tener acceso a metodos y propiedades para poder modificarlos, en el ejemplo anterior utilizamos a resize. Veamos algunos de los disponibles:
- enabled: propiedad de valor booleano para saber si esta activo o no
- isEnabled: metodo para verificar el valor de la propiedad anterior
- setEnabled: metodo para establecer el valor de enabled
- height: propiedad para almacenar la altura del elemento
- width: propiedad para almacenar el ancho del elemento
- height(): devuelve el valor de la propiedad height
- width(): devuelve el valor de la propiedad width
- resize(ancho, alto): establece nuevos valores para width y height respectivamente
- setMinimumWidth: establece el valor minimo para el ancho de un elemento
- setMinimumHeight: establece el valor minimo para el alto de un elemento
- setMaximumWidth: establece el valor maximo para el ancho de un elemento
- setMaximumHeight: establece el valor maximo para el alto de un elemento
Todas estas propiedades y metodos nos resultaran especialmente utiles para cuando debamos repartir los elementos en la ventana mediante un layout pero sobre este tema hablaremos un poco mas adelante en el post. Siguiendo con los metodos/funciones que disponemos, veamos los slots publicos que mas usaremos (y hemos usado) en nuestros elementos QWidget:
- close: cierra el widget
- hide: esconde al widget (similar a setVisible(false))
- lower: mueve el widget hacia abajo en el stack de su padre
- raise: mueve el widget hacia arriba en el stack de su padre
- setWindowTitle: establece el titulo de una ventana
- setWindowIcon: establece el icono de una ventana
- style: propiedad que almacena el estilo del widget
Para modificar el valor de la propiedad style se puede usar al metodo setStyleSheet pasandole una cadena que describa al estilo del widget. Tambien se puede usar setStyle pero el argumento que debemos pasar un objeto de tipo QStyle.
Una buena idea de usar Qt es que casi tiene todo lo necesario para nuestros proyectos. Si bien es muy raro que tengamos que crear nuestros propios widgets, pero aun asi podemos hacerlo. Por ejemplo, cuando hablamos de señales y slots en este post, donde creamos una clase para nuestra etiqueta personalizada y esta la hicimos heredera de QLabel. Esto mismo lo podemos hacer para la clase QWidget, de la siguiente manera:
class MiWidget : public QWidget
{
Q_OBJECT
public:
// seccion publica
signals:
// lista de señales
{public | private | protected} slots:
// lista de slots
};
La clase sera como una clase comun pero con dos etiquetas agregadas como son señales y slots. La seccion de señales no pueden tener un modificador de acceso pero para los slots si. Estos pueden ser publicos, privados o protegidos, con la misma conducta que tienen en las clases. Como vimos, tenemos varias maneras de poder manejar los distintos elementos, pero vamos a hablar sobre algunos de los que tenemos disponibles:
- QCheckBox: representa a un checkbox con una etiqueta
- QDateEdit: este es usado para establecer una fecha
- QDateTimeEdit: similar al anterior pero permite establecer la hora tambien
- QLabel: se usa para mostrar un texto y tambien una imagen
- QLineEdit: elemento para ingresar/mostrar/editar un texto en un sola linea
- QProgressBar: elemento que representa una barra de progreso horizontal
Ya tenemos los elementos y la ventana que los contiene pero ahora pasaremos a ver como ubicar a estos en el contenedor. Para ello, tenemos unos elementos que se encargan de los layout. Estos tambien son widgets encargados de ordenar al resto a traves de la forma de layout. Esta pensado principalmente a tener ordenado todos los widgets de una manera sencilla para la experiencia del desarrollador.
Pasemos a hablar sobre cuales las clases de gestion de layout. Una de las mayores ventajas de utilizar estas clases es que automaticamente reajustan el tamaño y la posicion cuando el contenedor cambia su tamaño, otra ventaja que tenemos es la posibilidad de ordenarlos mediante codigo y no solamente depender de un compositor de UI. Si bien disponemos del Qt Creator para manejar los widgets por lo general, los desarrolladores prefieren escribir un codigo que se encargue de manejarlos. Veamos las clases que disponemos para poder ordenar los elementos:
- QHBoxLayout
- QVBoxLayout
- QGridLayout
- QFormLayout
Estas clases son todas herederas de QLayout, la que se encarga verdaderamente de ubicar correctamente a los elementos. Esta a su vez en una clase base abstracta heredera de la clase Object pero esta clase no es heredera de QWidget porque no tiene nada que ver con el renderizado de los elementos sino solamente con la organizacion de los mismos en el widget contenedor. En general, no es necesario implementar nuestro propio gestor de layout pero en caso de necesitarlo deben hacerlo heredero de QLayout y proveer implementacion para las siguiente funciones:
- addItem()
- sizeHint()
- setGeometry()
- itemAt()
- takeAt()
- minimumSize()
Como dijimos, las clases comentadas anteriormente deberian ser mas que suficientes para poder gestionar los elementos en el contenedor. Para entender el concepto vamos a modificar el ejemplo anterior de la siguiente manera:
#include <QtWidgets>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QWidget* ventana = new QWidget;
QPushButton* btn1 = new QPushButton("Tinchicus");
QPushButton* btn2 = new QPushButton("Enzo");
QPushButton* btn3 = new QPushButton("Marta");
QPushButton* btn4 = new QPushButton("Kavito");
QVBoxLayout* layout = new QVBoxLayout;
layout->addWidget(btn1);
layout->addWidget(btn2);
layout->addWidget(btn3);
layout->addWidget(btn4);
ventana->setLayout(layout);
ventana->show();
return app.exec();
}
Seguimos creando la ventana pero ahora en lugar de tener un solo boton crearemos cuatro pero no los asignaremos a la ventana. Lo siguiente sera crear el layout para los botones, en este caso usaremos a QVBoxLayout, este genera un orden vertical de los elementos, y luego mediante addWidget agregaremos cada uno de los botones anteriores en el layout. Con nuestro layout completo, lo siguiente sera asignarlo a la ventana y finalmente mostrar la ventana y devolver la aplicacion. Si lo compilan y ejecutan deben tener lo siguiente:

Este layout como mencionamos anteriormente los ordena en forma vertical, si reemplazan a la funcion QVBoxLayout por QHBoxLayout (y el constructor tambien) en el codigo en lugar de mostrar en vertical lo hara de forma horizontal. Tomemos el codigo anterior y vamos a modificarlo de la siguiente manera:
#include <QtWidgets>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QWidget* ventana = new QWidget;
QPushButton* btn1 = new QPushButton("Tinchicus");
QPushButton* btn2 = new QPushButton("Enzo");
QPushButton* btn3 = new QPushButton("Marta");
QPushButton* btn4 = new QPushButton("Kavito");
QGridLayout* layout = new QGridLayout;
layout->addWidget(btn1, 0,0);
layout->addWidget(btn2, 0,1);
layout->addWidget(btn3, 1,0);
layout->addWidget(btn4, 1,1);
ventana->setLayout(layout);
ventana->show();
return app.exec();
}
La unica modificacion fue en el layout donde pasamos a utilizar un grid (cuadricula o tabla) ty para ello usamos a QGridLayout. Observen que como arguumento para la funcion addWidget pasamos tres valores que son: el elemento a agregar, la fila y la columna de la fila anterior.. En este caso, usamos solo dos filas y dos columnas. Como siempre, la primer posicion de ambos siempre sera 0 y a partir de este se ira incrementando. El resto del codigo sigue siendo el mismo, compilemos y veamos como es la nueva salida:

Obviamente podemos agregar mas elementos y distribuirlos de otra forma pero tambien disponemos de otra forma. Para verlo en accion, modifiquemos el codigo anterior de la siguiente manera:
#include <QtWidgets>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QWidget* ventana = new QWidget;
QPushButton* btn1 = new QPushButton("Tinchicus");
QPushButton* btn2 = new QPushButton("Enzo");
QPushButton* btn3 = new QPushButton("Marta");
QPushButton* btn4 = new QPushButton("Kavito");
QVBoxLayout *vertical = new QVBoxLayout;
vertical->addWidget(btn1);
vertical->addWidget(btn2);
QHBoxLayout *horizontal = new QHBoxLayout;
horizontal->addWidget(btn3);
horizontal->addWidget(btn4);
vertical->addItem(horizontal);
ventana->setLayout(vertical);
ventana->show();
return app.exec();
}
En este caso, vamos a juntar dos layouts. Primero creamos uno vertical con QVBoxLayout donde le asignamos dos botones. Para luego crear otro layout pero esta vez horizontal con QHBoxLayout y le agregamos los dos botones faltantes. Lo siguiente sera agregar el segundo layout como item del primero y en ventana establecemos al primer layout. Compilemos y veamos como es la nueva salida:

Observen como nos mezclo ambos layouts y asi podemos hacer multiples combinaciones de acuerdo a nuestra necesidad. Aqui cubrimos dos aspectos basicos a la hora de crear una GUI para nuestros codigos mediante Qt. Ya que vimos como agregarlos en una sola ventana asi como tambien la forma basica de distribuirlos en esta. Tanto la distribucion como otras conductas podemos personalizarlas, tal como mencionamos aqui y en este post con señales y slots. Lo dejamos en esto bien basico porque Qt necesita un serie de post y seccion para el solo….. lo cual puede ocurrir en un futuro.
En resumen, hoy hemos visto unos ejemplos mas para Qt, como agregar elementos en una ventana, un resumen basico de algunas conductas y como distribuir los elementos o widgets en una ventana. Espero les haya resultado de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donación
Es para mantenimento del sitio, gracias!
$1.50
