Tutorial de Qt

64
Tutorial de Qt - Capítulo 1 Resumen En nuestro primer programa mostraremos la típica frase "Hola Mundo!". Solo contiene lo indispensable para poner en marcha una aplicación Qt. La siguiente imagen es una captura de lo que vamos a hacer: Veamos el código completo de la aplicación: #include <QApplication> #include <QPushButton> int main(int argc, char *argv[]) { QApplication app(argc, argv); QPushButton hello("Hola Mundo!"); hello.show(); return app.exec(); } Explicación #include <QApplication> Esta linea incluye la definición de la clase QApplication . Solo tiene que haber un objeto QApplication en cada aplicación con GUI que use Qt. QApplication maneja los diferentes recursos de la aplicación, como la fuente por defecto y el cursor. #include <QPushButton> Esta linea incluye la definición de la clase QPushButton . Para cada clase de la API de Qt existe un fichero de cabecera con el mismo nombre que contiene su definición. Un QPushButton es un botón de la GUI que el usuario puede pulsar y soltar. Maneja su propio look and feel, como cualquier otro QWidget . Un widget es un objeto de la interfaz de usuario que puede dibujar gráficos y procesar entradas por parte del usuario. El programador puede cambiar tanto el aspecto general como otras muchas

Transcript of Tutorial de Qt

Page 1: Tutorial de Qt

Tutorial de Qt - Capítulo 1

Resumen

En nuestro primer programa mostraremos la típica frase "Hola Mundo!". Solo contiene lo indispensable para

poner en marcha una aplicación Qt. La siguiente imagen es una captura de lo que vamos a hacer:

Veamos el código completo de la aplicación:

#include <QApplication>#include <QPushButton>

int main(int argc, char *argv[]){  QApplication app(argc, argv);

  QPushButton hello("Hola Mundo!");

  hello.show();  return app.exec();}

Explicación

#include <QApplication>

Esta linea incluye la definición de la clase QApplication. Solo tiene que haber un objeto QApplication en

cada aplicación con GUI que use Qt. QApplication maneja los diferentes recursos de la aplicación, como la

fuente por defecto y el cursor.#include <QPushButton>

Esta linea incluye la definición de la clase QPushButton. Para cada clase de la API de Qt existe un fichero de

cabecera con el mismo nombre que contiene su definición.

Un QPushButton es un botón de la GUI que el usuario puede pulsar y soltar. Maneja su propio look and feel,

como cualquier otro QWidget. Un widget es un objeto de la interfaz de usuario que puede dibujar gráficos y

procesar entradas por parte del usuario. El programador puede cambiar tanto el aspecto general como otras

muchas propiedades menores (como el color), asi como el contenido del widget. Un QPushButton puede

mostrar un texto o un QIcon.

int main(int argc, char *argv[]){

Page 2: Tutorial de Qt

La función main() es el punto de entrada del programa. Casi siempre que usemos Qt, main() solo necesitará

realizar algún tipo de inicialización antes de pasar el control a la biblioteca Qt, la cual le comunicará al

programa como actuar con el usuario a través de los eventos que genere.

El parámetro argc es el numero de argumentos pasados por la linea de ordenes, y argv es el array que

contiene dichos argumentos. Esto es una definición estándar de C++.

  QApplication app(argc, argv);

El objeto app es la instancia de QApplication de este programa. Pasamos argc y argv al constructor

de QApplication para que pueda procesar los argumentos de la linea de ordenes (como -display). Cada vez

que un argumento es reconocido por Qt, se elimina de argv y consecuentemente argc se decrementa. Para

mas detalles puedes ver QApplication::arguments().

El objeto QApplication debe crearse ante de usar cualquier elemento de la GUI de Qt.

  QPushButton hello("Hello world!");

Despues de QApplication viene el primer código relacionado con la interfaz, hemos creado un botón.

Establecemos que el botón muestre el texto "Hola Mundo!". Como no hemos especificado una ventana padre

(por ejemplo mediante el segundo argumento del constructor de QPushButton), el botón será una ventana en

si misma, con su propio marco de venta y su barra de titulo.

El tamaño del botón está determinado por su propio tamaño por defecto. Podríamos llamar

a QWidget::move() para asignarle una posición determinada al widget, pero por ahora vamos a permitir que

el administrador de ventanas elija su posición.

  hello.show();

Un widget nunca es visible al usuario cuando lo creamos, debemos llamar a QWidget::show() para hacerlo

visible.  return app.exec();}

Aquí es donde main() pasa el control a Qt. QCoreApplication::exec() terminará cuando se salga de la

aplicación (QCoreApplication es la clase base de QApplication. Implementa el núcleo deQApplication, la

funcionalidad no-GUI y puede usarse para desarrollar aplicaciones sin GUI).

Page 3: Tutorial de Qt

En QCoreApplication::exec(), Qt recibe y procesa los eventos del usuario y del sistema y los pasa a los

widgets apropiados.

Pasemos a compilar y ejecutar nuestro primer programa.

Compilar y ejecutar la aplicación.

Una vez creado el archivo .cpp en un directorio de trabajo, el siguiente paso es crear el makefile de Qt en

dicho directorio. Para crear un makefile de Qt vamos a usar qmake, la herramienta de trabajo que incorpora

Qt.

Ejecutamos las dos siguientes sentencias desde una terminal en nuestro directorio de trabajo para crear el

makefile.

qmake -projectqmake

La primer orden indica a qmake que cree un archivo de proyecto (.pro). La segunda le dice a qmake que use

el archivo .pro para crear el makefile.

Ahora podemos ejecutar make para compilar el programa, y si todo ha ido bien, ya podemos ejecutar nuestra

primera aplicación Qt!.

Ejercicios.

Intenta redimensionar la ventana. Pulsa el botón. Intenta ejecutar el programa con la opción -geometry (por

ejemplo -geometry 100x200+10+20).

ResumenEste ejemplo es una continuación de la ventana creada en el capitulo 1. Vamos a hacer que la aplicación se cierre correctamente cuando el usuario se lo diga.

También vamos a usar un tipo de letra mas atractivo de la que se muestra por defecto.

Veamos el código completo de la aplicación:#include <QApplication>#include <QFont>#include <QPushButton>

int main(int argc, char *argv[])

Page 4: Tutorial de Qt

{        QApplication app(argc, argv);

        QPushButton quit("Quit");        quit.resize(75, 30);        quit.setFont(QFont("Times", 18, QFont::Bold));

        QObject::connect(&quit, SIGNAL(clicked()), &app, SLOT(quit()));

        quit.show();        return app.exec();}

Explicación

#include <QFont>

Como vamos a usar QFont en nuestro programa, tenemos que incluir QFont.

        QPushButton quit("Quit");

Esta vez el botón mostrara el texto Quit, y eso será lo que el programa haga cuando lo pulsemos.

        quit.resize(75, 30);

Hemos elegido otro tamaño para el botón ya que el texto es algo mas corto que "Hola Mundo!". También podríamos haber usado QFontMetrics para establecer el tamaño adecuado, o permitir que QPushButton eligiera un tamaño razonable por defecto.         quit.setFont(QFont("Times", 18, QFont::Bold));

Elegimos una nueva fuente para el botón: Times y negrita de 18 puntos. También es posible cambiar la fuente por defecto de toda la aplicación mediante QApplication::setFont().         QObject::connect(&quit, SIGNAL(clicked()), &app, SLOT(quit()));

QObject::connect() es quizás la característica mas importante de Qt. Ten en cuenta que connect() es una función estática de QObject, no confundirla con la función connect() de la biblioteca de sockets de Berkeley.

La llamada a connect() establece una conexión "en una sola dirección" entre dos objetos de Qt (objetos que heredan de QObject, directa o indirectamente). Cada objeto de Qt puede tener signals (para mandar mensajes) y slots (para recibir mensajes). Todos los widgets son objetos de Qt ya que heredan de QWidget, que a su vez hereda de QObject.

En nuestro caso, la señal clicked() de quit se conecta al slot quit() de app, así cuando se pulsa el botón, se termina la ejecución de la aplicación.

Page 5: Tutorial de Qt

La documentación de Signals and slots explica este mecanismo en profundidad.

Compilar y ejecutar la aplicación.Podemos compilar y ejecutar la aplicación de forma similar al capitulo 1. Si pulsamos el botón Quit, vemos como la aplicación termina su ejecución.

Ejercicios.Intenta redimensionar la ventana. Pulsa el botón para cerrar la aplicación.

¿Existe alguna otra señal de de QPushButton que puedas conectar al botón? (sugerencia: QPushButton hereda la mayor parte de su funcionalidad de QAbstractButton).

ResumenEn el tercer capítulo vamos a ver como crear widgets padres y widgets hijos de la forma mas sencilla posible: creando un padre y un solo hijo.

#include <QApplication>#include <QFont>#include <QPushButton>#include <QWidget>

int main(int argc, char *argv[]){        QApplication app(argc, argv);

        QWidget window;        window.resize(200, 120);

        QPushButton quit("Quit", &window);        quit.setFont(QFont("Times", 18, QFont::Bold));        quit.setGeometry(10, 40, 180, 40);        QObject::connect(&quit, SIGNAL(clicked()), &app, SLOT(quit()));

        window.show();        return app.exec();}

Page 6: Tutorial de Qt

Explicación

#include <QWidget>

Añadimos la cabecera de QWidget para poder usarla.

        QWidget window;

Creamos simplemente un widget. La clase QWidget es la clase base de todos los objetos de la interfaz de usuario. Un widget es el átomo de la interfaz de usuario: captura el ratón, el teclado y otros eventos del administrador de ventanas, y dibuja una representación de si mismo en la pantalla. Un widget queda recortado por su widget padre y por widgets que estan delante de él.

A un widget que no está relacionado con un widget padre, como el que hemos creado, se le llama ventana. Normalmente las ventanas tienen su propio marco de ventana y una entrada en la barra de tareas, proporcionado por el administrador de ventanas. Un widget sin widget padre siempre es una ventana independiente y su posición inicial en la pantalla está controlada por el administrador de ventanas.

        window.resize(200, 120);

Establecemos el ancho de la ventana a 200 pixeles a la altura a 120 pixeles.

        QPushButton quit("Quit", &window);

Acabamos de crear un hijo :P. Este QPushButton se ha creado definiendo un widget padre (window). Un widget hijo siempre se muestra en el area del padre, y cuando se muestra es recortado por los limites del padre. Por defecto se ancla a la esquina superior izquierda, en la posición (0, 0).

        quit.setGeometry(10, 40, 180, 40);

La funcion QWidget::setGeometry() tiene cuatro argumentos: los dos primeros son las coordenadas x e y de la esquina superior izquierda del botón (relativas al widget padre), y los dos últimos son la anchura y la altura del botón. El resultado es un botón que ocupa desde la posición (10, 40) hasta la posición (190, 80).

        window.show();

Cuando mostramos un widget padre, este llamará a la función show() de cada uno de sus hijos (excepto aquellos que se ocultaron explicitamente mediante QWidget:hide()).

Los lectores del tutorial que ya hayan estudiado la documentación de QObject recordarán que cuando se invoca al destructor de un QObject, si el QObject tiene hijos, el destructor

Page 7: Tutorial de Qt

invocado llamará automáticamente al destructor de cada hijo. Puede parece que el destructor del botón quit se invocará dos veces al final de main(), una cuando su padre (window) sale de su ámbito y el destructor elimina el botón porque es hijo suyo, y otra cuando el botón sale de su ámbito.No hay necesidad de preocuparse en este caso, ya que el código es correcto. De todas formas, existe un caso en el que el programador debe ser consciente del orden de la destrucción de objetos en la pila (puedes ver la explicación del orden de construcción/destrucción de QObjects aqui).

Ejecutar la aplicación.A diferencia del capitulo 2 del tutorial, el botón ya no llena toda la ventana, sino que se mantiene en la posición (10, 40) dentro de la ventana con un tamaño (180, 40), debido a la llamada a QWidget::setGeometry().

Ejercicios.Intenta redimensionar la ventana, ¿Cómo cambia el botón? ¿Qué sucede con la altura del botón si se ejecuta el programa con un tipo de letra mas grande?¿Qué ocurre si intentas hacer la ventana muy pequeña?

ResumenEn este capítulo vamos a ver como crear nuestro propio widget y como controlar el tamaño mínimo y máximo de dicho widget.

#include <QApplication>#include <QFont>#include <QPushButton>#include <QWidget>

class MyWidget : public QWidget{        public:        MyWidget(QWidget *parent = 0);};

MyWidget::MyWidget(QWidget *parent)        : QWidget(parent){

Page 8: Tutorial de Qt

        setFixedSize(200, 120);

        QPushButton *quit = new QPushButton(tr("Quit"), this);        quit->setGeometry(62, 40, 75, 30);        quit->setFont(QFont("Times", 18, QFont::Bold));

        connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));}

int main(int argc, char *argv[]){        QApplication app(argc, argv);        MyWidget widget;        widget.show();        return app.exec();}

Explicación

class MyWidget : public QWidget{        public:        MyWidget(QWidget *parent = 0);};

Lo primero que hacemos es crear una nueva clase. Como hereda de QWdiget, la nueva clase podrá ser un widget (y quizá una ventana independiente) o un widget hijo (como el QPushButton del capítulo anterior).

La clase solo tiene un miembro, el constructor (además de los miembros heredados de QWdiget). El constructor es un constructor estándar de widget de Qt; deberías incluir siempre un constructor similar cuando crees un widget.

El argumento del constructor es el widget padre. Para crear una ventana independiente con el widget debes especificar un puntero nulo como padre. Como puedes ver, el widget es por defecto una ventana independiente.

MyWidget::MyWidget(QWidget *parent)

La implementación del constructor empieza aquí. Como la mayoría de los widgets, simplemente pasa el argumento parent al constructor de QWdiget.

        : QWidget(parent){        setFixedSize(200, 120);

Page 9: Tutorial de Qt

Ya que el widget no sabe como manejar el redimensionado, fijamos su tamaño. En el siguiente capítulo veremos como un widget puede responder al redimensionado por parte del usuario.

        QPushButton *quit = new QPushButton(tr("Quit"), this);        quit->setGeometry(62, 40, 75, 30);        quit->setFont(QFont("Times", 18, QFont::Bold));

Creamos y establecemos un widget hijo de nuestro widget (el padre del nuevo widget es this, es decir, la instancia de MyWidget).

La función tr() marca la cadena "Quit" para que pueda ser traducida, haciendo posible cambiarla en tiempo de ejecución según los archivos de traducción. Es un buen habito usar tr() en todas las cadenas visibles al usuario en el caso de que decidas traducir mas tarde tu aplicación a otros idiomas.

Ten en cuenta de que quit es una variable local del constructor. MyWdiget no hace un seguimiento de ella; Qt es quien lo hace y la borrará automáticamente cuando el objeto MyWdiget sea destruido (No hay nada malo en borrar un hijo cuando lo desees, el hijo avisará automáticamente a Qt de su muerte inmediatamente).

La llamada a QWidget::setGeometry() establece la posición y el tamaño del widget en la pantalla. Es equivalente a llamar a QWidget::move() seguido de QWidget::resize.

        connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));}

El puntero qApp es una variable global declarada en el fichero cabecera QApplication, y apunta a la instancia única de QApplication en la aplicación.

int main(int argc, char *argv[]){        QApplication app(argc, argv);        MyWidget widget;        widget.show();        return app.exec();}

Instanciamos nuestro nuevo hijo, lo mostramos y ejecutamos la aplicación.

Ejecutar la aplicación.El comportamiento del programa es muy similar al del capítulo anterior, la diferencia reside en la manera en la que lo hemos implementado. Aunque no son exactamente iguales. Por ejemplo, intenta redimensionar la ventana para verlo.

Page 10: Tutorial de Qt

Ejercicios.Intenta crear otro objeto MyWidget en main(), ¿Qué ocurre?.Prueba a añadir mas botones o a incluir otros widgets a parte de QPushButton.

ResumenEn el quinto capítulo del tutorial vamos a ver como crear y conectar varios widgets entre ellos usando signals y slots, y como manejar el redimensionado de varios widgets en nuestra aplicación.

#include <QApplication>#include <QFont>#include <QLCDNumber>#include <QPushButton>#include <QSlider>#include <QVBoxLayout>#include <QWidget>

class MyWidget : public QWidget{        public:                MyWidget(QWidget *parent = 0);};

MyWidget::MyWidget(QWidget *parent)        : QWidget(parent){        QPushButton *quit = new QPushButton(tr("Quit"));        quit->setFont(QFont("Times", 18, QFont::Bold));

        QLCDNumber *lcd = new QLCDNumber(2);        lcd->setSegmentStyle(QLCDNumber::Filled);

        QSlider *slider = new QSlider(Qt::Horizontal);        slider->setRange(0, 99);        slider->setValue(0);

        connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));        connect(slider, SIGNAL(valueChanged(int)),

Page 11: Tutorial de Qt

                lcd, SLOT(display(int)));

        QVBoxLayout *layout = new QVBoxLayout;        layout->addWidget(quit);        layout->addWidget(lcd);        layout->addWidget(slider);        setLayout(layout);}

int main(int argc, char *argv[]){        QApplication app(argc, argv);        MyWidget widget;        widget.show();        return app.exec();}

Explicación

class MyWidget : public QWidget{        public:                MyWidget(QWidget *parent = 0);};

MyWidget::MyWidget(QWidget *parent)        : QWidget(parent){        QPushButton *quit = new QPushButton(tr("Quit"));        quit->setFont(QFont("Times", 18, QFont::Bold));

        QLCDNumber *lcd = new QLCDNumber(2);        lcd->setSegmentStyle(QLCDNumber::Filled);

lcd es un QLCDNumber: un widget que muestra un número como si fuera un LCD. Vamos a hacer que lcd muestre dos dígitos y estableceremos la propiedad QLCDNumber::segmentStyle a QLCDNumber::Filled para que sea mas legible.

        QSlider *slider = new QSlider(Qt::Horizontal);        slider->setRange(0, 99);        slider->setValue(0);

El usuario puede usar un QSlider para ajustar un valor entero dentro de un rango. Con estas tres instrucciones creamos un slider horizontal, establecemos su rango de 0 a 99 y su valor inicial a 0.

Page 12: Tutorial de Qt

        connect(slider, SIGNAL(valueChanged(int)),                lcd, SLOT(display(int)));

Usamos el mecanismo de signals y slots para conectar la señal valueChanged() del slider al slot display() del LCD.

Cada vez que el valor del slide cambie, este emitirá el nuevo valor lanzando la signal valueChanged(). Como esta señal está conectada al slot display() del LCD, se llamará al slot cuando la señal sea emitida. Ten en cuenta que ninguno de los objetos sabe sobre el otro (esencial en la programación con componentes).

Por otra parte, los slots son funciones miembro normales y siguen las reglas de acceso normal en C++.

        QVBoxLayout *layout = new QVBoxLayout;        layout->addWidget(quit);        layout->addWidget(lcd);        layout->addWidget(slider);        setLayout(layout);

MyWidget ahora usa un QVBoxLayout para manejar la geometría de sus widgets hijos. Por esta razón ya no necesitamos especificar las coordenadas en la pantalla para cada widget hijo tal como hicimos en el capítulo 4. Además, usar un layout asegura que se redimensionen los widgets hijos cuando la ventana se redimensione. Por tanto añadimos los widgets quit, lcd y slider al layout mediante QBoxLayout::addWidget().

La función QWidget::setLayout() establece el layout de MyWidget. Esto hace que el layout sea hijo de MyWidget, por lo que no tenemos que preocuparnos de borrarlo, la relación padre-hijo asegura que será borrado junto a MyWidget. Además, la llamada QWidget::setLayout() ajusta automaticamente los widgets en el layout como hijos de MyWidget. Por eso no tenemos que especificar this como padre en los widgets quit, lcd y slider.

En Qt, los widgets pueden ser hijos de otros widgets (por ejemplo mediante this) o pueden no tener padre. Un widget se puede añadir a un layout, lo cual hace que el layout sea el responsable de manejar la geometría de dicho widget, pero el layout nunca puede actuar como un padre en si. Es mas, el constructor de QWidget toma un puntero a QWidget como padre, y QLayout no hereda de QWidget.

Ejecutar la aplicación.El LCD de números refleja los cambios hechos en el slider, y los widgets se redimensionan de forma correcta. Date cuenta de que el widget LCD cambia de tamaño cuando se cambia el tamaño de la ventana (porque puede), pero los otros siguen teniendo el mismo tamaño (lo contrario sería sería extraño).

Page 13: Tutorial de Qt

Ejercicios.Intenta cambiar el LCD añadiendo mas dígitos o cambiando el modo (QLCDNumber::setMode()). Incluso puedes añadir cuatro botones para establecer la base del número (decimal, hexadecimal, octal o binaria).También puedes probar a cambiar el rango del slider.¿Tal vez hubiera sido mejor usar un QSpinBox en vez de un slider?Intenta hacer que la aplicación se cierre si se produce un desbordamiento en el LCD.

Otra Guia:

Tutorial de Qt 4: Nuestro primer programa, “Hola Mundo”

En este artículo vamos a crear y explicar a detalle la clásica primera aplicación en programación, esta vez con Qt.

El código de un Hola Mundo en Qt es el siguiente

123456789101112

#include <QApplication>#include <QLabel> int main(int argc, char *argv[]){ QApplication app(argc, argv); QLabel *label = new QLabel("Hola Mundo!");  label->show();  return app.exec();}

12

#include <QApplication>#include <QLabel>

Incluimos los archivos de cabecera que utilizaremos para el ejemplo, QApplication es una clase que representa una aplicación gráfica de Qt, es la encargada de administrar el flujo de ejecución y la configuración principal de la aplicación. QLabel es una clase que representa a un control de interfaz de usuario etiqueta, el cual es generalmente utilizado para mostrar texto no editableen pantalla.

4 int main(int argc, char *argv[])

Declaramos nuestra función main en la cual comenzará la ejecución de nuestro programa, es necesario especificar los argumentos de línea de comandos argc (un entero que contiene el número de argumentos) y argv (un arreglo/matriz que contiene el valor de cada uno de los argumentos) ya que al crear un objeto de la clase QApplication es necesario especificarlos.

6 QApplication app(argc, argv);

Page 14: Tutorial de Qt

Crea el objeto QApplication llamado app y pasa como parámetros los argumentos de línea de comandos.

7 QLabel *label = new QLabel("Hola Mundo!");

Crea un apuntador a un objeto QLabel llamado label, y lo inicializa con la sentencia new QLabel(“Hola Mundo!”), la cual reserva memoria para la etiqueta que contendrá el texto que queremos mostrar en pantalla, el cual especificamos como argumento del constructor. Es conveniente crear la variable label como apuntador ya que de esta forma Qt se hará cargo de gestionar la memoria asignada a este elemento.

9 label->show();

Muestra la etiqueta en pantalla. Qt se encargará de crear una ventana para poder mostrar la etiqueta en pantalla ya que nosotros no hemos asignado alguna.

11 return app.exec();

Inicia el hilo principal de la aplicación a partir de este momento el framework toma el control de la aplicación y responde a la interacción del usuario con los controles de interfaz gráfica de acuerdo a todo lo especificado anteriormente. La sentencia return regresa al sistema operativo la respuesta de la ejecución del programa una vez que ha finalizado, está respuesta tipicamente será cero en caso de que la aplicación se haya ejecutado exitosamente.

Compilación y Ejecución

Guardamos el archivo como holamundo.cpp o cualquier otro nombre con extensión “.cpp”. Abrimos una terminal en la ubicación de nuestro archivo holamundo.cpp y ejecutamos los siguientes comandos.

qmake -project

Crea un archivo de proyecto para nuestra aplicación

qmake holamundo.pro

Crea un archivo de proyecto específico para la plataforma o SO en el que estamos trabajando

make

Generar un archivo ejecutable correspondiente a nuestra aplicación.

./holamundo

Ejecuta el archivo ejecutable generado por el compilador al procesar nuestro código.

Page 15: Tutorial de Qt

Si todo ha ido bien deberías ver una ventana parecida a la siguiente

Tutorial de Qt4: Diálogos, comunicación con el usuario (Parte II)

En el artículo anterior revisamos la primera de las dos formas principales de utilizar diálogos en Qt, esto es creando clases que hereden de QDialog, implementando la funcionalidad de estas clases y gestionando las respuestas que recibimos a través de la función QDialog::exec()

En este artículo veremos la segunda forma de utilizar diálogos en una aplicación de Qt, esto es, utilizando las clases de diálogos estándar que nos proporciona Qt, estas clases son:

QMessageBox Permite mostrar mensajes de notificación al usuario. QFileDialog Permite mostrar un diálogo que sirve para seleccionar un archivo o carpeta

del sistema de archivos. QInputDialog Permite mostrar un diálogo con un widget para que el usuario puede

introducir información. QColorDialog Muestra un diálogo para que el usuario pueda seleccionar un color. QPrintDialog Muestra un diálogo para especificar configuraciones de la impresora.

A continuación mostraremos un ejemplo de uso de estos diálogos mediante una traducción/adaptación de el ejemplo Standar Dialogs de la documentación oficial de Qt, esta documentación la podemos encontrar en la dirección: http://qt.nokia.com/doc/4.6

El ejemplo se compone de los siguientes archivos:

Ventana.h Ventana.cpp main.cpp

Los archivos Ventana.h y Ventana.cpp componen la clase Ventana, la cual representa la ventana principal de la aplicación de ejemplo. Esta clase esta compuesta por dos columnas de widgets, una de ellas está compuesta por botones; Cada uno de ellos servirá para mostrar un diálogo estándar que nos permitirá obtener un dato del usuario. La segunda columna se

Page 16: Tutorial de Qt

compone de etiquetas y en cada una de ellas escribiremos la información que proporcionó el usuario a través del diálogo correspondientes. Dicha ventana se muestra en la siguiente imagen.

A continuación explicamos el código del archivo Ventana.cpp:

1234567891011121314

#include "ventana.h"#include <QPushButton>#include <QLabel>#include <QGridLayout> #include <QInputDialog>#include <QColorDialog>#include <QFileDialog>#include <QFontDialog>#include <QMessageBox>#include <QErrorMessage> Ventana::Ventana(){

QGridLayout* layoutPrincipal = new QGridLayout;

De las líneas 1 a 11 incluimos los archivos de cabecera que necesitamos para este ejemplo.En la línea 13 comienza el constructor de nuestra clase. En la línea 15 declaramos el layout con el que organizamos los componentes de nuestra ventana.

171819

botonObtenerTexto = new QPushButton(trUtf8("Obtener Texto"));botonObtenerEntero = new QPushButton(trUtf8("Obtener Entero"));

(...)32333435

etiquetaObtenerTexto = new QLabel(trUtf8("\t\t\t\t"));etiquetaObtenerEntero = new QLabel(trUtf8("\t\t\t\t"));etiquetaObtenerDoble = new QLabel(trUtf8("\t\t\t\t"));

(...)

De las líneas 17 a 45 creamos los widgets que utilizaremos en el ejemplo. No mostramos todas las líneas debido a que el código es muy repetitivo y las líneas son muy similares. En dónde escribimos (…) van líneas iguales a las anteriores pero para los demás widgets. El

Page 17: Tutorial de Qt

código del ejemplo se puede descargar mediante los links de la parte inferior de este artículo.

A partir de la línea 17 creamos los botones que servirán para mostrar cada uno de los diálogos estándar de Qt. A partir de la línea 32 y hasta la 45 creamos las etiquetas en las que escribiremos el valor de retorno de cada uno de los diálogos.

47484950

etiquetaObtenerTexto->setFrameStyle(QFrame::Box);etiquetaObtenerEntero->setFrameStyle(QFrame::Box);etiquetaObtenerDoble->setFrameStyle(QFrame::Box);

(...)62636465

layoutPrincipal->addWidget(botonObtenerTexto, 0, 0);layoutPrincipal->addWidget(etiquetaObtenerTexto, 0, 1);layoutPrincipal->addWidget(botonObtenerEntero, 1, 0);

(...)

93949596

connect(botonObtenerTexto, SIGNAL(clicked()), this, SLOT(obtenerTexto()));

connect(botonObtenerEntero, SIGNAL(clicked()), this, SLOT(obtenerEntero()));

connect(botonObtenerDoble, SIGNAL(clicked()), this, SLOT(obtenerDoble())); (...)

De las líneas 47 a 60 establecemos un marco para las etiquetas que mostrarán la respuesta de los diálogos. En las líneas 62 a 89 configuramos la apariencia de la interfaz de usuario utilizando un QGridLayout. Y finalmente, de las líneas 93 a 106 conectamos cada botón con su slot correspondiente, cada slot mostrará un diálogo distinto para cada botón y procesará la respuesta del usuario.

A partir de la línea 109 comienza la implementación de los slots, en todos ellos realizamos las siguiente acciones:

1. Creamos una variable para almacenar la información que ingresa el usuario por medio del diálogo.

2. Ejecutamos el diálogo para obtener la información del usuario y el valor de respuesta, este último está determinado por el botón que presiona el usuario.

3. Evaluamos el valor de respuesta del diálogo.4. Dependiendo del valor de la respuesta decidimos de que manera procesar la información

capturada, si es que la hay.

A continuación revisamos los slots que conectamos con cada uno de los botones, comenzaremos con los slots que hacen uso de los diálogos que nos ofrece la clase QInputDialog.

109110111112113114

void Ventana::obtenerTexto(){

QString texto = QInputDialog::getText(this, trUtf8(""), trUtf8(""), QLineEdit::Normal, trUtf8(""), &ok); 

if(ok)

Page 18: Tutorial de Qt

115116117118119120121122123124125126127128129130131132133134135136137138

etiquetaObtenerTexto->setText(texto);} void Ventana::obtenerEntero(){

int entero = QInputDialog::getInt(this, trUtf8(""), trUtf8(""), 42, 41, 43, 1, &ok);

if(ok)etiquetaObtenerEntero-

>setText(QString::number(entero));} void Ventana::obtenerDoble(){

double doble = QInputDialog::getDouble(this, trUtf8(""), trUtf8(""), 9.9, 5, 15, 2, &ok);

if(ok)etiquetaObtenerDoble->setText(QString::number(doble));

} void Ventana::obtenerElemento(){

QStringList listaElementos;listaElementos << "Elemento 1" << "Elemento 2" << "Elemento

3";QString elemento = QInputDialog::getItem(this, trUtf8(""),

trUtf8(""), listaElementos, 0, false, &ok);if(ok)

etiquetaObtenerElemento->setText(elemento);}

De la línea 109 a la 115 implementamos el slot obtenerTexto, en él mostramos un diálogo que nos permitirá obtener un valor de texto capturado por el usuario. Este diálogo lo ejecutamos mediante la función

QString QInputDialog::getText ( QWidget * parent, const QString & title, const QString & label, QLineEdit::EchoMode mode = QLineEdit::Normal, const QString & text = QString(), bool * ok = 0, Qt::WindowFlags flags = 0 )

Está función recibe como parámetros:

Un apuntador al widget que deseamos establecer como su padre. El texto que se mostrará en la barra de título del diálogo.

Page 19: Tutorial de Qt

El texto que mostrará el diálogo. El modo (EchoMode) en el que se mostrará el texto ingresado. Aqui podemos establecer

un valor de la enumeración EchoMode el cual indicará si el texto debe ser visible, que no se muestre o que se muestren caracteres para enmascarar contraseñas (como asteriscos)

El valor predeterminado que se mostrará en el campo de texto Un apuntador a una variable que almacena el valor que indica que botón fue presionado. Las flags (banderas u opciones) del diálogo, las cuales establecen propiedades del sistema

de ventanas para un widget, como los botones que se muestran en la barra de título o si debe mostrar barra de título o no. Los valores posibles son parte de la enumeración Qt::WindowFlags

Si el usuario no cierra el diálogo y en cambio presiona algún botón, entonces escribimos el valor de la respuesta en la etiqueta correspondiente.

De la línea 117 a 122 implementamos el slot obtenerEntero, en él mostramos un diálogo que contiene una spinBox que permitirá al usuario establecer un valor numérico entero. Este diálogo lo ejecutamos mediante la función

int QInputDialog::getInt ( QWidget * parent, const QString & title, const QString & label, int value = 0, int min = -2147483647, int max = 2147483647, int step = 1, bool * ok = 0, Qt::WindowFlags flags = 0 )

Los primeros tres y los dos últimos parámetros de está “familia” de funciones y de algunos de los otros diálogos estándar son iguales, indican el widget padre, el título del diálogo, el texto que se mostrará en el diálogo, un apuntador a la variable donde se almacenará la respuesta al diálogo y una lista de flags u opciones del diálogo.

A partir del cuarto parámetro y en orden, los parámetros específicos de este diálogo son:

El valor predeterminado que al que se establecerá la spinbox cuando se muestre el diálogo El valor mínimo al que se puede establecer el valor de la spinbox El valor máximo al que se puede establecer el valor de la spinbox La cantidad en que se incrementará o decrementará el valor de la spinbox al presionar las

flechas del extremo (step o paso)

De las líneas 124 a 129 implementamos el slot obtenerDoble, en él mostramos un diálogo muy similar al que del slot obtenerEntero con la diferencia de que el valor de la spinbox

Page 20: Tutorial de Qt

podrá ser un valor decimal o de punto flotante de doble precisión. Este diálogo lo ejecutamos mediante la función

double QInputDialog::getDouble ( QWidget * parent, const QString & title, const QString & label, double value = 0, double min = -2147483647, double max = 2147483647, int decimals = 1, bool * ok = 0, Qt::WindowFlags flags = 0 )

Los parámetros de esta función son muy similares a la función getInt salvo por el séptimo parámetro, el cuál indica el número de decimales del número, el valor por defecto es de uno.

De la línea 131 a 138 implementamos el slot obtenerElemento, en él mostramos un diálogo que contiene una comobox que permite al usuario elegir un valor de una lista que indiquemos. Este diálogo lo ejecutamos mediante la función

QString QInputDialog::getItem ( QWidget * parent, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true, bool * ok = 0, Qt::WindowFlags flags = 0 )

Esta función recibe del cuarto al sexto parámetro:

Una lista de cadenas de texto que serán los elementos de la combobox La posición del elemento seleccionado por defecto, si no se especifica será cero Un valor booleano que indica si la combobox será editable

140 void Ventana::obtenerColor()

Page 21: Tutorial de Qt

141142143144145146147148149150151152153154155

{QColor color = QColorDialog::getColor();if(color.isValid()) {

etiquetaObtenerColor->setText(color.name());etiquetaObtenerColor->setPalette(QPalette(color));etiquetaObtenerColor->setAutoFillBackground(true);

}} void Ventana::obtenerFuente(){

QFont fuente = QFontDialog::getFont(&ok);if(ok)

etiquetaObtenerFuente->setText(fuente.toString());}

De las líneas 140 a 148 implementamos el slot obtenerColor, en el mostramos un diálogo que contiene controles especializados para permitir que el usuario eliga un color. Este diálogo lo mostramos mediante la función

QColorDialog::getColor( const QColor & initial, QWidget * parent, const QString & title, ColorDialogOptions options = 0 )

Esta función recibe como parámetros:

Un objeto de la clase QColor que indica el color inicial que se establecerá en el diálogo, si no se especifica ninguno el color blanco será el seleccionado

El widget padre del diálogo El título del diálogo Miembros de la enumeración ColorDialogOptions, que permiten establecer algunas

propiedades del diálogo como mostrar canal alfa o usar el diálogo nativo del sistema operativo

De la línea 150 a 155 implementamos el slot obtenerFuente, el cual muestra un diálogo que incluye controles especiales para que el usuario pueda seleccionar una fuente para el texto. Dicho diálogo se muestra mediante la función

Page 22: Tutorial de Qt

QFont QFontDialog::getFont(bool *ok, QWidget *parent)

Dicha función tiene múltiples sobrecargas en las cuales se pueden establecer valores iniciales y configuraciones del diálogo similares a las de los diálogos anteriores pero en este ejemplo utilizamos una función que sólo recibe como parámetros el apuntador a la variable que almacena la respuesta que da el usuario al diálogo y un apuntador al widget padre de este diálogo.

157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186

void Ventana::obtenerDirectorioExistente(){

QString directorio = QFileDialog::getExistingDirectory(this, trUtf8(""), etiquetaObtenerDirectorioExistente->text(), QFileDialog::ShowDirsOnly);

if(!directorio.isEmpty())etiquetaObtenerDirectorioExistente-

>setText(directorio);} void Ventana::obtenerArchivoAbrir(){

QString filtroSeleccionado;QString Nombre = QFileDialog::getOpenFileName(this,

trUtf8(""),

etiquetaObtenerArchivoAbrir->text(),

trUtf8("Todos los archivos (*);;Archivos de Cabecera C/C++ (*.h);;Archivos de Código Fuente C++ (*.cpp)"),

&filtroSeleccionado, 0);if (!Nombre.isEmpty())

etiquetaObtenerArchivoAbrir->setText(Nombre);} void Ventana::obtenerArchivosAbrir(){

QStringList archivos = QFileDialog::getOpenFileNames(

Page 23: Tutorial de Qt

187188189190191192193194195196197198199

this,

trUtf8(""),"",

trUtf8("Todos los Archivos (*);;Archivos de Cabecera C/C++ (*.txt);;Archivos de Código Fuente C++ (*.cpp)")); 

if (archivos.count()) {etiquetaObtenerArchivosAbrir-

>setText(QString("[%1]").arg(archivos.join(", ")));}

} void Ventana::obtenerArchivoGuardar(){

QString nombreArchivo = QFileDialog::getSaveFileName(this,

trUtf8(""),

etiquetaObtenerArchivoGuardar->text(),

trUtf8("Todos los Archivos (*);;Archivos de Cabecera C/C++ (*.txt);;Archivos de Código Fuente C++ (*.cpp)")); 

if (!nombreArchivo.isEmpty())etiquetaObtenerArchivoGuardar->setText(nombreArchivo);

}

De las líneas 157 a 207 implementamos los slots que hacen uso de las funciones estáticas de la clase QFileDialog.

De la línea 157 a 162 implementamos el slot obtenerDirectorioExistente en el cual ejecutamos un diálogo que mostrará una ventana de exploración del sistema de archivos y que nos permitirá seleccionar una carpeta o directorio. Este diálogo lo mostramos con la función

QString getExistingDirectory ( QWidget * parent = 0, const QString & caption = QString(), const QString & dir = QString(), Options options = ShowDirsOnly )

Page 24: Tutorial de Qt

Esta función recibe como parámetros

Un apuntador al widget padre del diálogo El título del diálogo La ruta del directorio en dónde se desea comenzar a buscar Miembros de la enumeración QFileDialog::Options que permiten configurar opciones del

diálogo como el sólo mostrar directorios o utilizar un diálogo no nativo

De la línea 176 a 187 implementamos el slot obtenerArchivoAbrir el cual funciona de manera muy similar al slot anterior con la diferencia de que este permite seleccionar un archivo en lugar de un directorio. Mostramos el diálogo utilizado en este slot con la función

QString QFileDialog::getOpenFileName ( QWidget * parent = 0, const QString & caption = QString(), const QString & dir = QString(), const QString & filter = QString(), QString * selectedFilter = 0, Options options = 0 )

En esta función el último y los tres primeros parámetros son iguales al de la función del slot anterior. Los parámetros propios de esta función son:

Como cuarto parámetro, una cadena que representa los filtros que podrán ser aplicados al diálogo, este filtro determina que tipo de archivo se muestra. Para cada tipo de archivo se escribe una descripción y entre paréntesis la extensión del tipo de archivo. Separamos cada tipo de archivo mediante dos caracteres punto y coma (;;).

Como quinto parámetro, una cadena que indique el filtro seleccionado actualmente.

De la línea 176 a la 187 implementamos el slot obtenerArchivosAbrir el cual muestra un diálogo casi igual al del slot anterior con la diferencia de que este permite al usuario seleccionar más de un archivo. Mostramos el diálogo utilizado en este slot con la función

QStringList QFileDialog::getOpenFileNames ( QWidget * parent = 0, const QString & caption = QString(), const QString & dir = QString(), const QString & filter = QString(), QString * selectedFilter = 0, Options options = 0 )

Page 25: Tutorial de Qt

Los parámetros de la función utilizada para ejecutar el diálogo son iguales a los de la función utilizada para abrir un solo archivo.

De la línea 189 a 199 implementamos el slot obtenerArchivoGuardar el cual muestra un diálogo que permite guardar un archivo al usuario y eligiendo su ubicación y especificando su nombre. El diálogo utilizado en este slot lo ejecutamos mediante la función

QString QFileDialog::getSaveFileName ( QWidget * parent = 0, const QString & caption = QString(), const QString & dir = QString(), const QString & filter = QString(), QString * selectedFilter = 0, Options options = 0 )

Los parámetros de esta función son iguales que los de la función utilizada para ejecutar el diálogo que permite abrir archivos. Si especificamos un nombre que coincida con el de un archivo existente se mostrará otro diálogo solicitando la confirmación del usuario, este diálogo muestra dos botones de respuesta: Aceptar y Cancelar.

201202203204205206207208209210

void Ventana::mostrarMensajeCritico(){

QMessageBox::StandardButton respuesta = QMessageBox::critical(this,trUtf8(""),trUtf8(""),QMessageBox::Abort | QMessageBox::Retry |

QMessageBox::Ignore); 

if (respuesta == QMessageBox::Abort)

Page 26: Tutorial de Qt

211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251

etiquetaMostrarMensajeCritico->setText(tr("Abortar"));else if (respuesta == QMessageBox::Retry)

etiquetaMostrarMensajeCritico->setText(tr("Reintentar"));

elseetiquetaMostrarMensajeCritico->setText(tr("Ignorar"));

} void Ventana::mostrarMensajeInformacion(){

QMessageBox::StandardButton respuesta;respuesta = QMessageBox::information(this, trUtf8(""),

trUtf8("Este es un mensaje de información"));if (respuesta == QMessageBox::Ok)

etiquetaMostrarMensajeInformacion->setText(tr("OK"));else

etiquetaMostrarMensajeInformacion->setText(tr("Escape"));} void Ventana::mostrarMensajePregunta(){

QMessageBox::StandardButton respuesta;respuesta = QMessageBox::question(this, trUtf8(""),

trUtf8("Este es un mensaje con una pregunta"),

QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);if (respuesta == QMessageBox::Yes)

etiquetaMostrarMensajePregunta->setText(tr("Sí"));else if (respuesta == QMessageBox::No)

etiquetaMostrarMensajePregunta->setText(tr("No"));else

etiquetaMostrarMensajePregunta->setText(tr("Cancelar"));} void Ventana::mostrarMensajeAdvertencia(){

QMessageBox msgBox(QMessageBox::Warning, trUtf8("QMessageBox::warning()"),

trUtf8("Este es un mensaje de advertencia"), 0, this);

msgBox.addButton(trUtf8("Guardar Otra Vez"), QMessageBox::AcceptRole);

msgBox.addButton(trUtf8("Continuar"), QMessageBox::RejectRole);

if (msgBox.exec() == QMessageBox::AcceptRole)etiquetaMostrarMensajeAdvertencia->setText(tr("Guardar

Otra Vez"));else

etiquetaMostrarMensajeAdvertencia->setText(tr("Continuar"));}

Page 27: Tutorial de Qt

A partir de la línea 201 y hasta el fin del archivo en la línea 251 implementamos los slots que muestran los diálogos de la case QMessageBox. Entre las líneas 201 y 215 implementamos el slot mostrarMensajeCritico el cual permite mostrar un diálogo con un icono de error que normalmente sirve para indicar que ocurrió algún error grave en la aplicación. Mostramos este diálogo mediante la función

StandardButton QMessageBox::critical ( QWidget * parent, const QString & title, const QString & text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton )

Dicha función nos devuelve un valor de la enumeración StandarButttons, la cual contiene todos los posibles valores que devuelve un diálogo al presionar cada uno de los botones disponibles, como: Aceptar, Cancelar, Reintentar, Sí, Sí a todo, No, Cancelar.

Las cuatro funciones de la clase QMessageBox que revisaremos y que nos sirven para mostrar un diálogo de información reciben los mismos parámetros, los cuales son:

Un apuntador al widget padre del diálogo El título del diálogo El texto que deseamos mostrar en el diálogo Una lista de valores de la enumeración StandarButton separadados por caracteres 2de

barra”, (el que se usa para un OR a nivel bit en C/C++) en donde cada valor indica que se debe mostrar su botón correspondiente

Un valor de la enumeración StandarButtons el cual indica que botón se establecerá como predeterminado, es decir sobre cual se hará un efectro de clic al presionar la tecla enter al estar el diálgo activo

Entre las líneas 217 y 225 implementamos el slot mostrarMensajeInformacion en el cual mostramos un diálogo que sirve para mostrar información al usuario, como un aviso sobre la conclusión de una tarea o una notificación de algún evento. Mostramos el diálogo utilizado mediante la función

StandardButton QMessageBox::information ( QWidget * parent, const QString & title, const QString & text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton )

Page 28: Tutorial de Qt

De la línea 227 a 239 implementamos el slot mostrarMensajePregunta en el cual mostramos un diálogo con icono de un signo de interrogación, este diálogo sirve para realizar una pregunta al usuario o solicitar su confirmación u aprobación para un proceso, como al guardar o borrar un archivo. Mostramos este diálogo mediante la función

StandardButton QMessageBox::question ( QWidget * parent, const QString & title, const QString & text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton )

Y finalmente de le la línea 241 a la 251 implementamos el slot mostrarMensajeAdvertencia en el cual mostramos un diálogo con que sirve para mostrar un mensaje de advertencia, como información sobre un error poco grave. Este diálogo lo mostramos mediante la función

StandardButton QMessageBox::warning ( QWidget * parent, const QString & title, const QString & text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton )

Con esa función concluimos la revisión del código del archivo Ventana.cpp. En el archivo main.cpp simplemente creamos un objeto de esta clase y lo mostramos en pantalla.

Page 29: Tutorial de Qt

Eso es todo en este artículo. En la siguiente parte de este tutorial veremos como utilizar los widgets QListWidget, QTableWidget y QTreeWidget, los cuales nos permiten visualizar un conjunto de datos a manera de lista, tabla o árbol de manera sencilla. Estos widgets son parte del framework modelo/vista que Qt provee.

Tutorial de Qt 4: QMainWindow, la ventana principal de la aplicación

En el artículo anterior de este tutorial vimos como implementar la funcionalidad de una aplicación gráfica de Qt utilizando señales y slots. En este artículo revisaremos a detalle un widget especial, QMainWindow, el cuál posee características especiales para ser utilizado como la ventana principal de las aplicaciones Qt. La estructura de la QMainWindow se puede ver en la siguiente imagen

Una QMainWindow puede estar compuesta de las siguientes cinco áreas o secciones:

Menu Bar como su nombre lo indica esta barra contiene menús, los cuales están compuestos por elementos de texto o etiquetas que indican las acciones que puede realizar la aplicación y que se ejecutan al hacer clic sobre ellas. Normalmente sólo existe una de ellas en la ventana y está colocada en la parte superior, debajo de la barra de título. Algunos ejemplos muy conocidos de menús que suelen colocarse en esta barra son Archivo, Edición, Herramientas o Ayuda.

Page 30: Tutorial de Qt

Toolbars al igual que la barra de menús, esta clase de barras, conocida como barra de herramientas está compuesta por las acciones que puede realizar la aplicación, con la diferencia de que en esta barra dichas acciones se muestran mediante iconos en lugar de etiquetas. Estas barras suelen estar ubicadas debajo de la barra de menús y podemos encontrar una o más de estas barras en una ventana. Un ejemplo muy conocido de iconos colocados en este tipo de barras son los de Guardar, representado por un diskette o Imprimir, representado por una impresora.

Status Bar Esta barra, conocida como barra estatus o de estado, normalmente está colocada en la parte inferior de la ventana, en ella se muestran mensajes informativos sobre el estado de la aplicación, las acciones que está realizando o la descripción del elemento al que estemos apuntando con el mouse.

Dock Widgets Este es un tipo de widgets que pueden ser acoplados o ajustados alrededor del widget central de una aplicación o permitir que “floten” libremente en el escritorio, al igual que las barras de herramientas contienen iconos y botones que permiten ejecutar acciones que proporciona la aplicación.

Central Widget Este widget representa el área de trabajo de una aplicación, como la tabla de celdas de una aplicación en hoja de cálculo o el área de texto de un procesador de textos.

Page 31: Tutorial de Qt

Podemos reconocer estás secciones en un buen número de aplicaciones, como ejemplo presentamos la ventana de Open Office Writer (clic para ampliar).

A continuación mostraremos un sencillo ejemplo de una aplicación que basada en una QMainWindow, la cual contendrá una etiqueta como widget central la cual cambiará el texto que muestra dependiendo de la acción que ejecutemos, estas acciones se encontrarán en una barra de menús y una barra de herramientas también incluiremos una barra de estatus.

La aplicación está compuesta por los siguientes tres archivos:

ventanaprincipal.h es el archivo de encabezado de la clase VentanaPrincipal, contiene la declaracion de las variables y la definición de las funciones que utilizaremos en esta aplicación.

ventanaprincipal.cpp es el archivo fuente de la clase VentanaPrincipal, contiene la implementación de las funciones declaradas en el archivo de encabezado.

main.cpp

A continuación revisaremos a detalle los archivos de la aplicación, sólo explicaremos las secciones que no hayan sido revisadas en partes anteriores de este tutorial o que sean relevantes en este contexto

ventanaprincipal.h

123456789101112131415

#ifndef VENTANAPRINCIPAL_H#define VENTANAPRINCIPAL_H #include <QMainWindow> class QLabel;class QToolBar;class QAction;class QMenu; class VentanaPrincipal : public QMainWindow{Q_OBJECT public:

Page 32: Tutorial de Qt

16171819202122232425262728293031323334

VentanaPrincipal(); private slots: void accionNuevoLanzada(); void accionAbrirLanzada(); void accionAcercaDeLanzada(); void accionSalirLanzada(); private: QMenu* menuArchivo; QMenu* menuAyuda; QToolBar* barraDeHerramientas; QAction* accionNuevo; QAction* accionAbrir; QAction* accionAcercaDe; QAction* accionSalir; QLabel* widgetCentral;};#endif

En la línea 4 incluimos el archivo de cabecera QMainWindow el cual contiene la definición de la clase en la que basaremos nuestra ventana principal.

En la línea 11 definimos nuestra clase VentanaPrincipal e indicamos que heredará de QMainWindow.

De la líneas 18 a 22 declaramos los slots por medio de los cuales implementaremos la funcionalidad de nuestra aplicación.

Y finalmente de las líneas 24 a 32 declaramos las variables que utilizaremos en la aplicación.

ventanaprincipal.cpp

12345678910111213141516171819

#include "ventanaprincipal.h" #include <QMenuBar>#include <QToolBar>#include <QLabel>#include <QStatusBar>#include <QMessageBox> VentanaPrincipal::VentanaPrincipal(){ menuArchivo = menuBar()->addMenu(trUtf8("&Archivo")); menuAyuda = menuBar()->addMenu(trUtf8("A&yuda"));  barraDeHerramientas = addToolBar(trUtf8("&Archivo"));  widgetCentral = new QLabel(trUtf8("Widget central")); widgetCentral->setFont(QFont("Sans-Serif", 25));  accionNuevo = new QAction(QIcon("iconos/nuevo.png"),

Page 33: Tutorial de Qt

202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576

trUtf8("&Nuevo"), this); accionNuevo->setShortcut(QKeySequence::New); accionNuevo->setStatusTip(trUtf8("Crear un nuevo archivo"));  accionAbrir = new QAction(QIcon("iconos/abrir.png"), trUtf8("&Abrir"), this); accionAbrir->setShortcut(QKeySequence::Open); accionAbrir->setStatusTip(trUtf8("Abrir un archivo existente"));  accionSalir = new QAction(QIcon("iconos/salir.png"), trUtf8("&Salir"), this); accionSalir->setShortcut(QKeySequence::Quit); accionSalir->setStatusTip(trUtf8("Salir de la aplicación"));  accionAcercaDe = new QAction(QIcon("iconos/salir.png"), trUtf8("&Acerca de"), this); accionAcercaDe->setShortcut(QKeySequence("Ctrl+d")); accionAcercaDe->setStatusTip(trUtf8("Información sobre esta aplicación"));  menuArchivo->addAction(accionNuevo); menuArchivo->addAction(accionAbrir); menuArchivo->addSeparator(); menuArchivo->addAction(accionSalir);  menuAyuda->addAction(accionAcercaDe);  barraDeHerramientas->addAction(accionNuevo); barraDeHerramientas->addAction(accionAbrir); barraDeHerramientas->addSeparator(); barraDeHerramientas->addAction(accionSalir);  setCentralWidget(widgetCentral); statusBar()->showMessage(trUtf8("Bienvenido")); setWindowTitle("Ventana Principal"); setMinimumSize(200, 200);  connect(accionNuevo, SIGNAL(triggered()), this, SLOT(accionNuevoLanzada()));  connect(accionAbrir, SIGNAL(triggered()), this, SLOT(accionAbrirLanzada()));  connect(accionAcercaDe, SIGNAL(triggered()), this, SLOT(accionAcercaDeLanzada()));  connect(accionSalir, SIGNAL(triggered()), this, SLOT(accionSalirLanzada()));} void VentanaPrincipal::accionNuevoLanzada(){ widgetCentral->setText(trUtf8("Acción \"Nuevo\" lanzada")); this->resize(QSize(widgetCentral->sizeHint().width(), 200));} void VentanaPrincipal::accionAbrirLanzada()

Page 34: Tutorial de Qt

777879808182838485

{ widgetCentral->setText(trUtf8("Acción \"Abrir\" lanzada")); this->resize(QSize(widgetCentral->sizeHint().width(), 200));} void VentanaPrincipal::accionAcercaDeLanzada(){ QMessageBox::about(this, this->windowTitle(), trUtf8("Aquí se debe colocar información sobre la aplicación y la compañia que la desarolla\n\nTutoriales, artículos y enlaces de programación en:\nhttp://www.programacion-linux.com"));} void VentanaPrincipal::accionSalirLanzada(){ exit(0);}

De las líneas 1 a 7 incluimos los archivos de cabecera necesarios para implementar la aplicación.

En las línea 11 inicializamos la variable menuArchivo la cual representa un menú que podemos incluir en la barra de menús de la QMainWindow, para lograrlo utilizamos las funciones

QMenuBar* QMainWindow::menuBar()

Devuelve una referencia a una barra de menús que es creada al llamar a la función por primera vez.

QMenu* QMenuBar::addMenu(QString &texto)

Devuelve una referencia a un menú que se creará al llamar a la función y que mostrará en pantalla el texto indicado en la cadena de caracteres que se pasa como parámetro. En la línea 12 realizamos lo mismo para el menú Ayuda.

En la línea 14 inicializamos la variable que representa a una barra de herramientas. La función utilizada es:

QToolBar* QMainWindow::addToolBar(QString &texto);

y trabaja de manera muy similar a las descritas anteriormente, es decir, devuelve una referencia a una QToolBara que se crea cuando se llama a la función y que mostrará en pantalla la cadena que se pasa como  parámetro.

En la línea 16 inicializamos la etiqueta que será utilizada como widget central en la aplicación. Y en la línea 17 establecemos la fuente que queremos que ocupe la etiqueta, esto se hace mediante la instrucción:

QLabel::setFont(QFont(QString &fuente, int tamanio));

Page 35: Tutorial de Qt

La cual recibe como parámetros un objeto QFont, el cual representa una fuente de texto y que a su vez recibe como parámetros el nombre de la fuente y el tamaño de la misma.

En la línea 19 inicializamos nuestra variable accionNuevo, del tipo QAction, mediante el constructor de la clase

QAction::QAction(QIcon(QString &archivo), QString &texto, QWidget* padre)

Este constructor recibe como parámetros un objeto QIcon, el cual representa un icono que se mostrará cuando la acción sea colocada dentro de una barra de herramientas y que a su vez recibe como parámetro una cadena de texto con la dirección dónde se encuentra el archivo de imágen que mostrará el icono, el segundo parámetro del constructor de la clase QAction es una cadena que indica el texto que se mostrará cuando la acción sea colocada dentro de una barra de menús y el último parámetro es el widget padre de la acción.

Antes de seguir debemos definir el concepto de QAction: Una QAction es una representación abstracta de un comando de la aplicación que puede ser ejecutado por el usuario.

En muchas aplicaciones los mismos comandos, acciones o funciones pueden ser ejecutados de diferentes maneras, ya sea mediante un elemento de la barra de menús, un icono de alguna barra de herramientas o una combinación de teclas, por mencionar algunos ejemplos. Una QAction nos es muy útil en este tipo de situación ya que puede estar asociada a múltiples widgets, gracias a esto será posible proporcionar la misma función en distintos lugares de la aplicación y de manera sincronizada, entonces podemos decir que una QAction proporciona una interfaz común para la ejecución de los comandos de la aplicación.

Siguiendo con el código, en la línea 20 establecemos un atajo de teclado para nuestra acción Nuevo, mediante la función

QAction::setShortcut(const QKeySecuence secuencia)

la cual recibe como parámetro un elemento de la enumeración QKeySecuence, dicha enumeración nos proporciona combinaciones estándar de teclas dependiendo de la configuración del sistema operativo en el que nos encontremos. Por ejemplo en el caso de mi sistemas operativo el elemento QKeySecuence::New esta relacionado con la combinación de teclas Ctrl+N sin embargo esto puede ser distinto en otro sistema operativo, pero al utilizar esta enumeración Qt se encargará de administrarlo y  en caso de que se requiera, asociarlo a otra combinación de teclas más adecuada en esa situación.

En la línea 21 establecemos el texto que deseamos que se muestre en la barra de estatus al posicionar el cursor del mouse sobre los widgets relacionados con la acción correspondiente. Esto se logra mediante la función:

QAction::setStatusTip(QString &texto)

Page 36: Tutorial de Qt

La cual recibe como parámetro una cadena con el texto que deseamos mostrar.

En las líneas 23 a 33 realizamos lo mismo para las acciones restantes.

En las líneas 35 a 38 agregamos tres de las acciones que creamos al menú Archivo. Esto lo hacemos a través de la función

QMenu::addAction(QAction* accion)

Con el fin de lograr un diseñod e interfaz de usuario más claro y atractivo en la línea 37 agregamos un separardor, utilizando la función

QMenu::addSeparator()

Un separador es una línea vertical u horizontal que separa las acciones que está colocadas dentro del mismo menú o barra de herramientas pero que pueden ser ubicadas en una categoría específica o diferente del resto de las acciones del mismo menú o barra de herramientas.

En la línea 40 agregamos la acción AcercaDe al menú Ayuda.

En las líneas 42 a 45 agregamos las acciones a la barra de herramientas de la aplicación utilizando las mismas funciones que utilizamos para agregarlas a los menús.

En la línea 48 creamos la barra de estatus mediante la función

QMainWindow::statusBar()

La cual funciona de manera muy similar a las funciones utilizadas para crear las otras barras de la ventana principal, es decir, creará una barra de estatus para la ventana la primera vez que es llamada.

En la misma línea utilizamos la función

QStatusBar::showMessage(QString &mensaje)

para mostrar un mensaje en la barra de estatus, en este caso mostramos la palabra “Listo” con el fin de indicar que la aplicación puede comenzar a utilizarse.

En las líneas 52 y 53 conectamos la acción accionNuevo con su slot correspondiente, esto lo realizamos mediante la función connect(), la cual revisamos a detalle en un artículo anterior. Debido a que una acción puede estar asociada a múltiples widgets no siempre será lanzada de la misma forma, debido a ello Qt nos proporciona la señal triggered() (lanzada o disparada) la cual se emitirá cada vez que un widget asociado a la señal sea activado, por ejemplo un clic sobre un botón lanzará una acción asociada al mismo mientras que una combinación de teclas lanzará dicha acción al ser presionada por el usuario.

Page 37: Tutorial de Qt

En las líneas 55 a 62 conectamos las acciones restantes a sus respectivos slots.

En la línea 65 comienza la implementación de los slots, los slots accionNuevoLanzada y accionAbriLanzada cambiarán el texto que se muestra en la etiqueta utilizada como widget central y redimensionarán la ventana para ajustarla al nuevo texto mostrado. El cambio de texto de la etiqueta se realiza mediante la función

QLabel::setText(QString &texto)

la cual recibe como parámetro una cadena de caracteres con el texto que se desea mostrar.

El cambio de tamaño de la ventana se realiza mediante la función

QMainWindow::resize(QSize(int width, int height))

esta función recibe como parámetro un objeto QSize, el cual es una estructura que incluye el ancho y alto de un widget y que a su vez recibe como parámetros dos enteros indicando el ancho y alto del widget, respectivamente.

También utilizamos la función sizeHint() la cual devuelve un objeto QSize con el tamaño requerido por el widget sobre el que se llamo la función.

En la línea 77 comienza la implementación del slot asociado a la acción acercaDe, en la línea 79 indicamos que al dispararse dicha acción se mostrará el conocido diálogo acerca de el cuál contiene información sobre la aplicación como versióno fecha de lanzamiento y sobre la compañia que creo la aplicación.

Finalmente en las líneas 82 a 85 implementamos el slot asociado a la acción salir, en la línea 84 utilizamos la función exit(int codigo) para indicar que deseamos salir de la aplicación, la aplicación devolverá un código el código de error indicado como parámetro. Normalmente un valor de cero indica que la aplicación termino normalmente, es decir, sin ningún error.

main.cpp

12345678910111213

#include "ventanaprincipal.h"#include <QApplication> int main(int argc, char* argv[]){ QApplication app(argc, argv);  VentanaPrincipal* ventanaPrincipal = new VentanaPrincipal;  ventanaPrincipal->show();  return app.exec();}

Page 39: Tutorial de Qt

Es todo en este artículo, en la siguiente parte del tutorial veremos como implementar un widget personalizado, el cual podremos utilizar en futuras aplicaciones que desarrollemos.

Tutorial de Qt 4: Layouts, organización de los Widgets

En el ejemplo anterior realizamos nuestra primera aplicación en Qt, el clásico Hola Mundo, en el cual solamente creamos una etiqueta con el texto “Hola Mundo!” y la mostramos en pantalla. Utilizamos este enfoque debido a que realizamos un programa que sólo serviría de ejemplo, pero en él se pueden apreciar serias deficiencias, tal vez la más notoria es que sólo es posible utilizar un elemento de interfaz gráfica (widget) a la vez, el cual en nuestro caso fue una etiqueta.

En este artículo veremos la forma de solucionar esto: utilizando Layouts.

Los Layouts son objetos que nos permiten organizar los widgets dentro de una ventana, en Qt disponemos de los siguientes tipos básicos de Layouts:

QHBoxLayout QVBoxLayout QGridLayout QFormLayout

A continuación describiremos brevemente estos layouts y mostraremos un ejemplo básico de su uso.

QHBoxLayout

Nos permite ordenar los widgets en filas, es decir, de manera horizontal.

Page 40: Tutorial de Qt

El código para crear una aplicación con un layout como el de la imagen anterior es el siguiente, explicaremos sólo las líneas de código que no hayan sido vistas a detalle en partes anteriores del tutorial:

1234567891011121314151617181920212223242526

#include <QObject>#include <QApplication>#include <QDialog>#include <QHBoxLayout>#include <QPushButton> int main(int argc, char *argv[]){ QApplication app(argc, argv);  QDialog *ventana = new QDialog(); QHBoxLayout *layout = new QHBoxLayout(); QPushButton *boton1 = new QPushButton(QObject::trUtf8("Botón 1")); QPushButton *boton2 = new QPushButton(QObject::trUtf8("Botón 2")); QPushButton *boton3 = new QPushButton(QObject::trUtf8("Botón 3"));  layout->addWidget(boton1); layout->addWidget(boton2); layout->addWidget(boton3);  ventana->setLayout(layout); ventana->setWindowTitle("QHBoxLayout"); ventana->show();  return app.exec();}

Las líneas 1 a 5 importan las bibliotecas necesarias para esta aplicación, QObject nos proveerá de la función trUtf8() necesaria para escribir cadenas con caracteres Unicode, en nuestro caso, caracteres propios del español como la ñ, o el acento (tilde).

QDialog es una clase que representa un diálogo de aplicación. Utilizamos un diálogo en lugar de una ventana principal buscando mantener la simplicidad del ejemplo. Un diálogo es una ventana mediante la cual el usuario y la aplicación se comunican. Algunos de sus usos son:

Informar al usuario sobre la ocurrencia de algún evento relevante como una notificación al terminar un proceso o un error al realizarlo.

Solicitar confirmación para realizar alguna acción como borrar o guardar un archivo. Solicitar información, como la palabra a buscar en un diálogo de buscar y reemplazar.

Page 41: Tutorial de Qt

QHBoxLayout es una clase que representa a nuestro layout horizontal. QPushButton es una clase que representa a un botón estándar.

111213

QDialog *ventana = new QDialog(); QHBoxLayout *layout = new QHBoxLayout(); QPushButton *boton1 = new QPushButton(QObject::trUtf8("Botón 1"));

En las líneas 11 a 13 creamos un nuevo diálogo, layout y botón mediante la sentencia new para ejecutar el constructor de cada clase, en este caso el constructor del botón es el único que recibe parámetros, este parámetro es una cadena de texto que contenga la etiqueta que debe mostrar el botón. Las líneas 14 y 15 crean los otros botones de la misma forma.

171819

layout->addWidget(boton1); layout->addWidget(boton2); layout->addWidget(boton3);

En las líneas 17 a 19 colocamos los botones dentro de nuestro layout mediante la función

addWidget(QWidget *widget, int stretch=0, Qt::Alignment aling=0)

Esta función recibe como parámetros un apuntador al widget que deseamos agregar, un entero que indica el indice de “flexibilidad” (stretch) del widget y un elemento de la enumeración Qt::Alignment, los últimos dos parámetros pueden omitirse y en caso de hacerlo se les asiga el valor de cero. El stretch indica la proporción de espacio disponible en el layout que el widget ocupará, es relativo al stretch indicado en los otros widgets que están dentro del layout, entre mayor sea el valor de stretch mayor será el espacio que ocupará el widget. La enumeración Qt:Alignment indica la alineación que tendrá el widget y puede tener los siguiente valores:

Horizontales: Qt::AlignLeft (izquierda), Qt::AlignRight (derecha), Qt::AlignHCenter (centrado horizontalmente), Qt::AlignJustify (justificado)

Verticales:Qt::AlignTop (superior/arriba), Qt::AlignBottom (inferior/abajo), Qt::AlignVCenter (centrado verticalmente)

Bidimensionales:Qt::AlignCenter (centrado horizontal y verticalmente)

Los widgets se colocan en el orden en que se ejecutan las instrucciones, de forma que en este layout el primer botón de izquierda a derecha (la dirección por default de este layout) es boton1 seguido de boton2 y por último boton3. Si queremos invertir el orden de los widgets podemos escribir las instrucciones en orden inverso o podemos indicar que nuestros widgets se añadan de derecha a izquierda con la instrucción

setDirection(QBoxLayout:RightToLeft)1718

ventana->setLayout(layout); ventana->setWindowTitle("QHBoxLayout");

En la línea 17 establecemos nuestro layout como el principal de la ventana, es decir el que indicará como se muestran los widgets en esa ventana. Y por último en la línea 18

Page 42: Tutorial de Qt

indicamos el título que queremos que muestre nuestra ventana, si no se especifica se utilizará el del nombre del archivo.

QVBoxLayout

Nos permite ordenar los widgets en columnas, es decir, de manera vertical.

El código para crear una aplicación con un layout como el de la imagen anterior es el siguiente:

1234567891011121314151617181920212223242526

#include <QObject>#include <QApplication>#include <QDialog>#include <QVBoxLayout>#include <QPushButton> int main(int argc, char *argv[]){ QApplication app(argc, argv);  QDialog *ventana = new QDialog(); QVBoxLayout *layout = new QVBoxLayout(); QPushButton *boton1 = new QPushButton(QObject::trUtf8("Botón 1")); QPushButton *boton2 = new QPushButton(QObject::trUtf8("Botón 2")); QPushButton *boton3 = new QPushButton(QObject::trUtf8("Botón 3"));  layout->addWidget(boton1); layout->addWidget(boton2); layout->addWidget(boton3);  ventana->setLayout(layout); ventana->setWindowTitle("QVBoxLayout"); ventana->show();  return app.exec();}

Si lo comparamos con el ejemplo anterior del QHBoxLayout, lo único que cambia es que nuestro objeto layout ahora es de tipo QVBoxLayout, el resultado de esto es que los widgets ahora se organizan de acuerdo a las reglas de este layout, es decir, de arriba hacia abajo. Si queremos invertir el orden en que se agregan los widgets al layout utilizamos la instrucción

Page 43: Tutorial de Qt

setDirection(QBoxLayout::BottomToTop);

QGridLayout

Nos permite ordenar los widgets a manera de tabla o rejilla.

El código para crear una aplicación con un layout similar al de la imagen es:

1234567891011121314151617181920212223242526

#include <QObject>#include <QApplication>#include <QDialog>#include <QGridLayout>#include <QPushButton> int main(int argc, char *argv[]){ QApplication app(argc, argv);  QDialog *ventana = new QDialog(); QGridLayout *layout = new QGridLayout(); QPushButton *boton1 = new QPushButton(QObject::trUtf8("Botón 1")); QPushButton *boton2 = new QPushButton(QObject::trUtf8("Botón 2")); QPushButton *boton3 = new QPushButton(QObject::trUtf8("Botón 3"));  layout->addWidget(boton1, 0, 0); layout->addWidget(boton2, 0, 1); layout->addWidget(boton3, 1, 0);  ventana->setLayout(layout); ventana->setWindowTitle("QGridLayout"); ventana->show();  return app.exec();}

Nuevamente cambiamos el tipo de nuestro objeto layout, ahora será de la clase QGridLayout.

La forma de agregar los widgets a este tipo de layout es ligeramente distinta, ahora lo haremos mediante la función

addWidget(QWidget *widget, int fila, int columna, Qt::Alignment align=0);

Esta función recibe como parámetros un apuntador al widget que deseamos agregar, dos enteros que indican la fila y columna, respectivamente, de la celda sobre la cual queremos

Page 44: Tutorial de Qt

agregar el widget en cuestión y un valor de la enumeración Qt::Alignment. Las filas y columnas comienzan a contarse desde cero de tal manera que la primera celda en la esquina superior izquierda tiene la posición fila=0, columna=0.

171819

layout->addWidget(boton1, 0, 0); layout->addWidget(boton2, 0, 1); layout->addWidget(boton3, 1, 0);

En la línea 17 colocamos al primer botón en la celda definida por la intersección de la fila cero con la columna cero, es decir, posición 0,0. Luego colocamos al boton2 y boton3 en las celdas 0,1 y 1,0 respectivamente.

El espacio vacío en la celda 1,1 se genera debido a que el QGridLayout crea tantas divisiones de filas y columnas como el número máximo de filas o columnas que indiquemos, en este caso dos, debido a la existencia de las filas y columnas uno y cero. Por ejemplo, si añadieramos los botones al layout mediante las líneas

layout->addWidget(boton1, 0, 0); layout->addWidget(boton2, 1, 1); layout->addWidget(boton3, 2, 2);

Obtendríamos el siguiente resultado:

Sin embargo habrá que tener en cuenta que las filas o columnas extras no serán visibles a menos que establezcamos el alto/ancho mínimo de cada fila/columna o que coloquemos un widget en la fila/columna correspondiente, en este último caso (que es lo que ha ocurrido en los dos ejemplos anteriores) el QGridLayout asigna automáticamente el alto/ancho mínimo de esta fila/columna con un valor igual al mínimo requerido por el widget en cuestión. Podemos establecer el ancho mínimo de una columna y el alto mínimo de una fila con las funciones:

setColumnMinimumWidth(int columna, int anchoMinimo )setRowMinimumHeight(int fila, int altoMinimo)

Por ejemplo si añadieramos los botones al layout mediante el siguiente código:

layout->addWidget(boton1, 0, 0);layout->addWidget(boton2, 1, 1);layout->addWidget(boton3, 3, 3);

Page 45: Tutorial de Qt

Se crearían cuatro filas y cuatro columnas, es decir, una fila y columna más que en el ejemplo anterior, pero al ejecutar el programa obtendríamos el mismo resultado que se muestra en la imagen pasada. Esto ocurre debido a que aunque la fila y columna con el número dos existen, estas tienen un alto y ancho de cero ya que no hemos colocado ningún widget en ellas ni hemos establecido el tamaño mínimo para ellas. Pero si después de la línea dónde agregamos el último botón al layout añadimos las líneas:

layout->setColumnMinimumWidth(2, 60);layout->setRowMinimumHeight(2, 20);

Obtendríamos el siguiente resultado:

QFormLayout

Nos permite ordenar los widgets de manera similar a la de formulario web, es decir, filas compuestas por un par de widgets, los cuales normalmente son una etiqueta y un campo de texto.

El código para crear una aplicación con un layout como el de la imagen anterior es el siguiente:

123456789101112

#include <QObject>#include <QApplication>#include <QDialog>#include <QFormLayout>#include <QPushButton> int main(int argc, char *argv[]){ QApplication app(argc, argv);  QDialog *ventana = new QDialog(); QVBoxLayout *layout = new QVBoxLayout();

Page 46: Tutorial de Qt

1314151617181920212223242526

QPushButton *boton1 = new QPushButton(QObject::trUtf8("Botón 1")); QPushButton *boton2 = new QPushButton(QObject::trUtf8("Botón 2")); QPushButton *boton3 = new QPushButton(QObject::trUtf8("Botón 3"));  layout->addRow(QObject::trUtf8("Botón 1:"), boton1); layout->addRow(QObject::trUtf8("Botón 2:"), boton2); layout->addRow(QObject::trUtf8("Botón 3:"), boton3);  ventana->setLayout(layout); ventana->setWindowTitle("QVBoxLayout"); ventana->show();  return app.exec();}

En este caso nuestro layout será del tipo QFormLayout y para añadir widgets utilizarermos la función

addRow(QLabel *etiqueta, QWidget *widget);

aunque también es posible utilizar la siguiente función sobre cargada, con el fin de evitar crear una etiqueta para cada uno de los widgets que deseeemos agregar:

addRow(const QString &amp;texto, QWidget *widget)171819

layout->addRow(QObject::trUtf8("Botón 1:"), boton1); layout->addRow(QObject::trUtf8("Botón 2:"), boton2); layout->addRow(QObject::trUtf8("Botón 3:"), boton3);

En las líneas 17 a 19 agregamos los widgets al layout, utilizamos la versión sobrecargada de addRow() en la que el primer parámetro es una cadena de texto con el fin de ahorrar código, debido a que en este ejemplo no necesitamos que el texto de alguna fila cambie y por lo tanto no es necesario conservar un apuntador hacia las etiquetas. Este tipo de layout es muy útil, por ejemplo, en la creación de formularios para la solicitud de información (como un registro de usuarios o un formulario de comentarios) en dónde debemos de indicar que información debe de capturar el usuario en cada campo.

Layouts Anidados

Normalmente las aplicaciones que desarrollemos no tendrán una interfaz tan sencilla como para ser diseñadas utilizando sólo un layout, para organizar los widgets de maneras más complejas utilizamos layouts anidados, es decir, un layout dentro de otro. La función que nos permite anidar layouts depende del tipo de layout que estemos utilizando, para QHBoxLayout y QVBoxLayout la función es:

addLayout(QLayout *layout, int Qt::Alignment align=0)

Para el QGridLayout además debemos especificar la fila y columna de la celda dónde deseamos agregar el layout, de la siguiente forma

addLayout(QLayout *layout, int fila, int columna, Qt::Alignment align=0)

Page 47: Tutorial de Qt

Para el QFormLayout se utiliza una función sobrecargada de addRow(), en una de las siguientes formas, dependiendo de la apariencia que deseemos lograr:

addRow(QLabel *label, QLayout *layout)addRow(QString &amp;texto, QLayout *layout)

Está función recibe como parámetros un apuntador a la etiqueta que contiene el texto que describe al layout o simplemente una QString con ese texto y un apuntador al layout que deseamos agregar.

addRow(QLayout *layout)

Esta función recibe cómo parámetro un apuntador al layout que deseamos agregar.

A continuación mostraremos un sencillo ejemplo de anidación de layouts para crear una interfaz de usuario muy conocida: un formulario de inicio de sesión.

12345678910111213141516171819202122232425262728293031323334353637

#include <QApplication>#include <QHBoxLayout>#include <QVBoxLayout>#include <QLabel>#include <QLineEdit>#include <QPushButton>#include <QDialog> int main(int argc, char *argv[]){QApplication app(argc, argv); QDialog *ventana = new QDialog();QHBoxLayout *layoutUsuario = new QHBoxLayout();QHBoxLayout *layoutContrasenia = new QHBoxLayout();QHBoxLayout *layoutBotones = new QHBoxLayout();QVBoxLayout *layoutPrincipal = new QVBoxLayout(); QLabel *etiquetaUsuario = new QLabel("Usuario");QLabel *etiquetaContrasenia = new QLabel("Password"); QLineEdit *campoUsuario = new QLineEdit();QLineEdit *campoContrasenia = new QLineEdit(); QPushButton *botonAceptar = new QPushButton("Aceptar");QPushButton *botonCancelar = new QPushButton("Cancelar"); layoutUsuario->addWidget(etiquetaUsuario);layoutUsuario->addWidget(campoUsuario); layoutContrasenia->addWidget(etiquetaContrasenia);layoutContrasenia->addWidget(campoContrasenia); layoutBotones->addStretch();layoutBotones->addWidget(botonAceptar);layoutBotones->addWidget(botonCancelar); 

Page 48: Tutorial de Qt

3839404142434445464748

layoutPrincipal->addLayout(layoutUsuario);layoutPrincipal->addLayout(layoutContrasenia);layoutPrincipal->addLayout(layoutBotones); ventana->setLayout(layoutPrincipal); ventana->setWindowTitle(QObject::trUtf8("Iniciar Sesión"));ventana->show(); return app.exec();}

Al ejecutar este código obtendremos una salida parecida a la siguiente imagen

En las líneas 1 a 7 incluimos los archivos de cabecera necesarios para desarrollar la aplicación, mientras que en las líneas 13 a 26 creamos los widgets que utilizaremos. En las líneas 28 y 29 colocamos los widgets del campo usuario en un QHBoxLayout, lo mismo hacemos para los campos de contraseña y para los botones. Con el fin de lograr una interfaz más agradable alineamos los botones a la derecha insertando un espacio en blanco al principio del QHBoxLayout mediante la instrucción

addStretch(int stretch=0);3839404142

layoutPrincipal->addLayout(layoutUsuario);layoutPrincipal->addLayout(layoutContrasenia);layoutPrincipal->addLayout(layoutBotones); ventana->setLayout(layoutPrincipal);

A partir de la línea 38 agregamos en el layout principal (el cual es un QVBoxLayout) el layout que contiene los controles de usuario, seguido por el que contiene los controles de contraseña y por último el que contiene los botones y finalmente en la línea 40 establecemos el layout principal de nuestra apliciación.

Es posible diseñar una interfaz de usuario utilizando distintas combinaciones de layouts, es cuestión de tiempo y experiencia poder encontrar aquella que sea más fácil y rápida de crear o la que se adapte mejor a las necesidades de nuestra aplicación. Para el ejemplo anterior un mejor diseño (considerando que requiere menos líneas) puede lograrse utilizando un QFormLayout en lugar de los primeros dos QHBoxLayout. El código es el siguiente:

1 #include <QApplication>

Page 49: Tutorial de Qt

2345678910111213141516171819202122232425262728293031323334353637

#include <QHBoxLayout>#include <QFormLayout>#include <QLineEdit>#include <QPushButton>#include <QDialog> int main(int argc, char *argv[]){QApplication app(argc, argv); QDialog *ventana = new QDialog();QHBoxLayout *layoutBotones = new QHBoxLayout();QFormLayout *layoutPrincipal = new QFormLayout(); QLineEdit *campoUsuario = new QLineEdit();QLineEdit *campoContrasenia = new QLineEdit(); QPushButton *botonAceptar = new QPushButton("Aceptar");QPushButton *botonCancelar = new QPushButton("Cancelar"); layoutBotones->addStretch();layoutBotones->addWidget(botonAceptar);layoutBotones->addWidget(botonCancelar); layoutPrincipal->addRow(QString("Usuario"), campoUsuario);layoutPrincipal->addRow(QString("Password"), campoContrasenia);layoutPrincipal->addRow(layoutBotones); ventana->setLayout(layoutPrincipal); ventana->setWindowTitle(QObject::trUtf8("Iniciar Sesión"));ventana->setWindowFlags(Qt::Window);ventana->show(); return app.exec();}

Al ejecutar este código obtenemos una salida similar a la siguiente

La cual tiene una apariencia muy similar a la del ejemplo anterior y que en mi opinión incluso se ve mejor, pero lo importante es que el número de líneas utilizadas se redujo un poco, pero es de suponer que en una aplicación de mayor tamaño el ahorro de líneas de código también será mayor.

Page 50: Tutorial de Qt

Tutorial Gtk+ 2: Instalacion de Gtk+ 2 en Linux

Gtk+ es, de manera parecida a Qt, un conjunto de herramientas usado para crear interfaz gráfica de usuario, escrito completamente en C, no se encuentra orientado a objetos, sin embargo “simula” estarlo,  al estar programado en C es bastante flexible con otros lenguajes y facilmente adaptable, la interfaz grafica de Gnome  (el entorno de escritorio de Ubuntu) esta creada con Gtk+.

Instalacion de Gtk con Gestor de paquetes.Instalar Gtk con un gestor de paquetes como es el Synaptic de Ubuntu es bastante sencillo ya que solamente necesitamos localizar la libreria con el nombre de “libgtk2.0-dev” y nuestro magico gestor de paquetes resolvera las dependencias de librerias necesarias para que todo funcione correctamente.

Instalacion de Gtk+ con paquetes de distribución (O la ruta escénica)

El primer paso es conseguir el paquete de distribución de la página www.gtk.org de la sección de descargas de la misma, el segundo es extraerlo a la carpeta donde tendremos todos nuestros archivos de origen, esto lo hacemos con los comandos:

tar xvfz gtk+-2.0.0.tar.gztar xvfj gtk+-2.0.0.tar.bz2

Despues de hacer esto nos ubicamos en la carpeta donde se contienen todos los demas archivos y ejecutamos el script llamado configure el cual crea archivos makefile adecuados al sistema operativo, la manera mas comun de hacer esto es:

./configure --prefix=/opt/gtk

Despues de hacer esto simplemente hacemos uso de los archivos recien creados e instalamos con los siguientes comandos:

makemake install

Despues de esto puede que sea necesario hacerle saber al sistema operativo acerca de las nuevas librerias dinámicas esto lo hacemos ejecutando:

ldconfig

Una vez hecho esto al fin hemos conseguido instalar Gtk+ en uestra maquina con Linux, si ocurrel agun fallo a pesar de que ya se encuentra instalado Gtk+, lo mas probable es que se trate de alguna libreria de la cual depende gtk para compilar/ejecutar, la manera mas fácil de comprobar que nuestro Gtk+ fue instalado con exito es ejecutar en nuestra liena de comandos el demo que viene jutno con Gtk+:

gtk-demo

Page 51: Tutorial de Qt

Con esto tenemos todo listo para crear nuestro “Hola Mundo” en Gtk+.