Inicio Rápido con Qt 4

download Inicio Rápido con Qt 4

of 67

Transcript of Inicio Rápido con Qt 4

Inicio Rpido con Qt 4En este tutorial cubrimos de manera rpida y sin entrar en mucho detalle, conceptos bsicos de Qt como Layouts o Signals/Slots. Revisamos la creacin de los ejemplos mediante cdigo fuente y mediante Qt Creator (prximamente).

Introduccin a QtPara una introduccin un poco ms completa puedes consultar la introduccin del tutorial creado para Zona Qt Qt es un framework para el desarrollo de aplicaciones multiplataforma creado por la compaia Trolltech y que actualmente es propiedad de Nokia, la funcin ms conocida de Qt es la de la creacin de interfaces de usuario, sin embargo no se limita a esto, ya que tambin provee varias clases para facilitar ciertas tareas de programacin como el manejo de sockets, soporte para programacin multihilo, comunicacin con bases de datos, manejo de cadenas de caracteres, entre otras. Qt utiliza C++ de manera nativa, pero ofrece soporte para otros lenguajes como Python mediante PyQt, Java mediante QtJambi, o C# mediante Qyoto. Qt es un framework muy poderoso, comparable con Swing de Java o .NET de Microsoft, adems ofrece una suite de aplicaciones para facilitar y agilizar las tareas de desarrollo, las aplicaciones que componen esta suite son: Qt

Assistant: Herramienta para visualizar la documentacin oficial de Qt. Qt Designer: Herramienta WYSIWYG para crear interfaces de usuario. Qt Linguist: Herramienta para la traduccin de aplicaciones. Qt Creator: IDE para el lenguaje C++, pero especialmente diseado para Qt, integra las primeras dos herramientas mencionadas. Qt es utilizado por empresas como Intel, Google o Dreamworks. Algunos ejemplos de aplicaciones desarrolladas utilizando Qt son: El

entorno de escritorio KDE Google Earth Skype Virtual Box Qt est disponible bajo las siguientes licencias: Qt

GNU GPL v. 3.0: Utilizada para el desarrollo de aplicaciones de cdigo abierto. Si se realizan cambios al cdigo fuente de Qt, estos tienen la obligacin de liberarse.

Qt

GNU LGPL v.2.1: Permite el desarrollo de aplicaciones comerciales bajo ciertas restricciones. Si se realizan cambios al cdigo fuente de Qt, estos tienen la obligacin de liberarse. Commercial: Es la nica licencia con costo, es utilizada para el desarrollo de aplicaciones propietarias o comerciales, incluye soporte y la posibilidad de liberar las aplicaciones desarrolladas bajo cualquier licencia. Si se ralizan cambios al cdigo fuente de Qt, estos no tienen la obligacin de ser compartidos. Puedes comenzar el tutorial de Qt en el artculo Instalacin de Qt.

Instalacin de Qt 4En este artculo revisamos algunas de las formas que existen de instalar y configurar el entorno de desarrollo de Qt, hablamos un poco de sus ventajas y desventajas e indicamos la forma de instalarlo. Instalar

Qt utilizando un asistente de instalacin Instalar Qt mediante la compilacin del cdigo fuente A continuacin, describimos cada una de ellas.

Instalar Qt utilizando un asistente de instalacinVentajas: Este mtodo tambin es sencillo de realizar. Permite facilmente mantenerse con la versin ms reciente de Qt. Permite instalar versiones anteriores de Qt si es que lo requerimos. Desventajas: Puede generar un poco de confusin debido a que, dependiendo de los permisos con los que realicemos la instalacin, las herramientas de Qt pueden o no ser agregadas al path por el instalador. Instrucciones: Descargar la versin que deseemos instalar, tpicamente la ms reciente, desde la pgina oficial de descargas de Qt: http://qt.nokia.com/downloads/ En dnde el nombre del instalador suele tener la forma: qt-sdk-[plataforma]-[arquitectura][versionlicencia]-[version]-[revision].[extension] Un ejemplo de ello es la versin 4.6.3 opensource de 32 bits para linux que lleva por nombre qt-sdk-linux-x86-opensource-2010.03.bin Despus ejecutamos el instalador y seguimos las instrucciones que nos muestra e indicamos la informacin que nos pide (path de instalacin, aceptar el acuerdo de licencia). Una vez terminada la instalacin podemos ejecutar el entorno de desarrollo integrado Qt Creator y comenzar a crear aplicaciones o revisar los impresionantes ejemplos :D. Si queremos utilizar las herramientas desde la terminal es necesario ejecutarlas indicando el path en el que estn instaladas, por ejemplo en linux, /home/usuario/qt-sdk-qt-sdk-linux-x86-opensource2010.03/qt/bin/qmake o si lo preferimos agregar al path dicha ruta para slo indicar el nombre del ejecutable. Si existe ms de una versin en el path del sistema suele tomar en cuenta la que aparece primero. Notas: Este mtodo puede generar algo de confusin con la versin que se est utilizando para compilar, sobre todo si se utiliza Qt Creator, ya que dentro de l se puede especificar con que

versin de las instaladas (y que se le haya indicado previamente) se desea compilar algn proyecto, sea o no la del path.

Instalar Qt mediante la compilacin del cdigo fuenteVentajas: A pesar de ser el mtodo ms complicado de los tres, se simplifica bastante gracias al script de configuracin y compilacin que se incluye, al cual slo debemos indicarle con que parmetros deseamos incluir o excluir en la construccin de nuestro entorno de desarrollo de Qt. Suele ser la forma ideal si requerimos alguna caracterstica adicional a las predeterminadas, como soporte para MySQL en Windows, o si deseamos utilizar una versin an en desarrollo. Desventajas: Aparte de ser la forma ms complicada de las tres, la compilacin de Qt toma bastante tiempo, dependiendo del harware de la mquina puede llegar a unas 10 horas o ms. Algunas veces los scripts de instalacin presentan algn problema que puede complicar todo ya que no se puede construir mediante los parmetros definidos en el asistente y habr que buscar que es lo que falla y cmo solucionarlo. Instrucciones: Descarga el cdigo fuente desde la pgina oficial de descargas de Qt: http:/qt.nokia.com/downloads Una vez descargado el archivo, lo descomprimimos, buscamos el script de configuracin, de nombre configure, lo ejecutamos y seguimos las instrucciones. Luego esperamos (un largo tiempo) a que termine la instalacin. Podemos agregar una versin compilada al Qt Creator y al path del sistema con el fin de utilizarla de manera ms cmoda. Es todo en este artculo de instalacin. Si tienes algn problema con tu instalacin puedes solicitar ayuda en la seccin Instalacin e Implementacin del Foro de Zona Qt.

Nuestro Primer Programa en Qt: "Hola Mundo"En este artculo vamos a crear y explicar a detalle la clsica primera aplicacin en programacin, esta vez con Qt. El cdigo de un Hola Mundo en Qt es el siguiente#include #include int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel *label = new QLabel("Hola Mundo!"); label->show(); } return app.exec();

Revisaremos el cdigo linea por lnea:

#include #include

En las primeras dos lneas incluimos los archivos de cabecera que utilizaremos para el ejemplo, QApplication es una clase que representa una aplicacin grfica de Qt, es la encargada de administrar el flujo de ejecucin y la configuracin principal de la aplicacin. QLabel es una clase que representa a un control de interfaz de usuario etiqueta, el cual es generalmente utilizado para mostrar texto no editable en pantalla.int main(int argc, char *argv[])

Declaramos nuestra funcin main en la cual comenzar la ejecucin de nuestro programa, es necesario especificar los argumentos de lnea de comandos argc (un entero que contiene el nmero 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.QApplication app(argc, argv);

Crea el objeto QApplication llamado app y pasa como parmetros los argumentos de lnea de comandos.QLabel label("Hola Mundo!");

Crea un objeto QLabel llamado label, y la cual contendr el texto que queremos mostrar en pantalla, el cual especificamos como argumento del constructor.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.return app.exec();

Inicia el hilo principal de la aplicacin a partir de este momento el framework toma el control de la aplicacin y responde a la interaccin del usuario con los controles de interfaz grfica de acuerdo a todo lo especificado anteriormente. La sentencia return regresa al sistema operativo la respuesta de la ejecucin del programa una vez que ha finalizado, esta respuesta tipicamente ser cero en caso de que la aplicacin se haya ejecutado exitosamente.

Construccin de un Proyecto Utilizando la TerminalCompilacin y ejecucin utilizando una consola o terminalEscribimos el texto del ejemplo en un archivo de texto sin formato utilizando una herramienta como el bloc de notas de windows o editores de texto plano de GNU/Linux como GEdit o Kate, guardamos el archivo como holamundo.cpp o cualquier otro nombre con extensin .cpp. Abrimos una terminal en la ubicacin de nuestro archivo holamundo.cpp y ejecutamos los siguientes comandos:

Para crear un archivo de proyecto para nuestra aplicacin ejecutamos el comando:qmake -project

Creamos un archivo de proyecto especfico para la plataforma o SO en el que estamos trabajando con el comando:qmake

Para especificar el archivo de proyecto a utilizar, muy til cuando existe ms de un archivo de proyecto en nuestro directorio de trabajo actual, ejecutamos el comando:qmake [nombre-de-archivo-de-proyecto].pro

Para generar el archivo ejecutable de nuestra aplicacin, ejecutamos el comando:make

o si utilizamos windows el comando ser:mingw32-make

Al igual que suceda con los archivos de proyecto, si existe ms de un archivo de construccin de proyecto habr que especificar el nombre del archivo que deseamos que se procese. Para ejecutar el archivo ejecutable generado por el compilador al procesar nuestro cdigo, utilizamos el comando:./holamundo

o si utilizamos windows, el comando ser:holamundo.exe

Si todo ha ido bien deberas ver una ventana parecida a la siguiente

Construccin de un Proyecto Utilizando Qt CreatorCompilacin y Ejecucin utilizando Qt Creator

Ejecutamos la aplicacin Qt Creator seleccionandola del men de aplicaciones de nuestro sistema.

Al hacerlo veremos la pantalla de bienvenida de Qt Creator

En ella seleccionamos la opcin "New File or Project..." del Men "File"

Veremos un asistente de creacin de nuevo proyecto, para este ejemplo seleccionaremos un proyecto vaco.

En el siguiente paso del asistente seleccionamos las plataformas (targets) para las cuales deseamos construir nuestra aplicacin Qt, para este ejemplo nos sirve cualquiera, nosotros elegimos Desktop/Escritorio En los pasos siguientes del asistente se nos solicitar el nombre del archivo e informacin sobre control de versiones, para el nombre nos sirve cualquiera, nosotros utilizamos HolaQt.cpp y para el control de versiones

por ahora basta con presionar "Finish"

Agregamos un nuevo archivo al proyecto, haciendo clic derecho en la carpeta principal del proyecto y seleccionando la opcin "Add New..." del

men contextual que aparece

Escribimos el cdigo del ejemplo y presionamos el botn de ejecutar y construir aplicacin. El botn de ejecutar y construir es el botn con una flecha color verde colocado en la parte inferior izquierda de la interfaz de Qt Creator, en la siguiente imagen est debajo del icono de una computadora y tiene un tooltip con el texto "Run Ctrl+R". Ctrl+R es el

atajo de teclado para ejecutar la accin que realiza este botn.

Esperamos a que la compilacin termine y veremos nuestro programa en ejecucin

Layouts de Qt. Organizacin de los widgetsEn el ejemplo anterior realizamos nuestra primera aplicacin en Qt, el clsico 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 slo servira de ejemplo, pero ese ejemplo tiene el gran inconveniente de que slo es posible utilizar un elemento de interfaz grfica (widget) a la vez, el cual en nuestro caso fue una etiqueta. En este artculo hablaremos acerca de los Layouts, los cuales nos ayudarn a solucionar situaciones como las del ejemplo anterior. Los Layouts son objetos que nos permiten organizar los widgets dentro de una ventana, en Qt disponemos de los siguientes tipos bsicos de Layouts: QHBoxLayout QVBoxLayout

QGridLayout QFormLayout

En las secciones de esta parte del tutorial describiremos brevemente estos layouts y mostraremos un ejemplo bsico de su uso. Tambin veremos que es posible anidar los layouts con el fin de crear interfaces de usuario ms complejas que las que se pueden lograr utilizando un slo layout.

QHBoxLayout Organizar Widgets de Manera HorizontalEl QHBoxLayout Nos permite ordenar los widgets en filas, es decir, de manera horizontal.

El cdigo para crear una aplicacin con un layout como el de la imagen anterior es el siguiente, explicaremos slo las lneas de cdigo que no hayan sido vistas a detalle en partes anteriores del tutorial:1. 2. 3. 4. 5. 6. #include #include #include #include #include

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

9.

QApplication app(argc, argv); QDialog ventana; QHBoxLayout *layout QPushButton *boton1 QPushButton *boton2 QPushButton *boton3

10.

11. 12. 13. 14. 15. 17. 18. 19. 21. 22.

16.

= = = =

new new new new

QHBoxLayout(&ventana); QPushButton(QObject::trUtf8("Botn 1")); QPushButton(QObject::trUtf8("Botn 2")); QPushButton(QObject::trUtf8("Botn 3"));

layout->addWidget(boton1); layout->addWidget(boton2); layout->addWidget(boton3); ventana.setWindowTitle("QHBoxLayout"); ventana.show();

20.

23.

24.25.

return app.exec(); }

Las lneas 1 a 5 importan las bibliotecas necesarias para esta aplicacin, QObject nos proveer de la funcin trUtf8() necesaria para escribir cadenas con caracteres Unicode, en nuestro caso, caracteres propios del espaol como la , o el acento (tilde). QDialog es una clase que representa un dilogo de aplicacin. Utilizamos un dilogo en lugar de una ventana principal buscando mantener la simplicidad del ejemplo. Un dilogo es una ventana mediante la cual el usuario y la aplicacin se comunican y los revisamos en un artculo siguiente del tutorial. Algunos de sus usos son: Informar

al usuario sobre la ocurrencia de algn evento relevante como una notificacin al terminar un proceso o un error al realizarlo. Solicitar confirmacin para realizar alguna accin como borrar o guardar un archivo. Solicitar informacin, como la palabra a buscar en un dilogo de buscar y reemplazar. QHBoxLayout es una clase que representa a nuestro layout horizontal. QPushButton es una clase que representa a un botn tpico.11. 12. 13.QDialog ventana; QHBoxLayout *layout = new QHBoxLayout(); QPushButton *boton1 = new QPushButton(QObject::trUtf8("Botn 1"));

En las lneas 11 a 13 creamos un nuevo dilogo, layout y botn mediante la sentencia new para ejecutar el constructor de cada clase, en el parmetro del constructor del layout horizontal es un apuntador a su widget padre, sobre el cual el layout tendr efecto, el parmetro del constructor del botn es la cadena de texto que mostrar el botn. Las lneas 14 y 15 crean los otros botones de la misma forma.17. 18. 19.layout->addWidget(boton1); layout->addWidget(boton2); layout->addWidget(boton3);

En las lneas 17 a 19 colocamos los botones dentro de nuestro layout mediante la funcinaddWidget(QWidget *widget, int stretch=0, Qt::Alignment aling=0)

Esta versin de esta funcin recibe como parmetros un apuntador al widget que deseamos agregar, un entero que indica el ndice de flexibilidad (stretch) del widget y un elemento de la enumeracin Qt::Alignment, los ltimos dos parmetros pueden omitirse y en caso de hacerlo se les asigna el valor de cero. El stretch indica la proporcin de espacio disponible en el layout que el widget ocupar, es relativo al stretch indicado en los otros widgets que estn dentro del layout, entre mayor sea el valor de stretch mayor ser el espacio que ocupar el widget. La enumeracin Qt:Alignment indica la alineacin 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 botn de izquierda a derecha (la direccin 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 aadan de derecha a izquierda con la instruccin setDirection(QBoxLayout:RightToLeft)21. 22.ventana.setLayout(layout); ventana.setWindowTitle("QHBoxLayout");

Y por ltimo en la lnea 21 indicamos el ttulo que queremos que muestre nuestra ventana, si no se especifica se utilizar el del nombre del archivo.

QVBoxLayout Organizar los Widgets de Manera VerticalEl QVBoxLayout Nos permite ordenar los widgets en columnas, es decir, de manera vertical.

El cdigo para crear una aplicacin con un layout como el de la imagen anterior es el siguiente:#include #include #include #include #include

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

{

QApplication app(argc, argv); QDialog ventana; QVBoxLayout *layout QPushButton *boton1 QPushButton *boton2 QPushButton *boton3 = = = = new new new new QVBoxLayout(); QPushButton(QObject::trUtf8("Botn 1")); QPushButton(QObject::trUtf8("Botn 2")); QPushButton(QObject::trUtf8("Botn 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 instruccinsetDirection(QBoxLayout::BottomToTop)

QGrid Layout. Organizar los Widgets en Forma TabularEl QGridLayout nos permite ordenar los widgets a manera de tabla o rejilla.

El cdigo para crear una aplicacin con un layout similar al de la imagen es:

1. 2. 3. 4. 5. 6.

#include #include #include #include #include

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

9.

10.

QApplication app(argc, argv); QDialog ventana; QGridLayout *layout QPushButton *boton1 QPushButton *boton2 QPushButton *boton3

11. 12. 13. 14. 15. 17. 18. 19. 21. 22. 23. 25.

= = = =

new new new new

QGridLayout(); QPushButton(QObject::trUtf8("Botn 1")); QPushButton(QObject::trUtf8("Botn 2")); QPushButton(QObject::trUtf8("Botn 3"));

16. layout->addWidget(boton1, 0, 0); layout->addWidget(boton2, 0, 1); layout->addWidget(boton3, 1, 1); ventana.setLayout(layout); ventana.setWindowTitle("QGridLayout"); ventana.show(); return app.exec(); }

20.

24. 26.

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 funcinaddWidget(QWidget *widget, int fila, int columna, Qt::Alignment align=0)

Esta funcin recibe como parmetros un apuntador al widget que deseamos agregar, dos enteros que indican la fila y columna, respectivamente, de la celda sobre la cual queremos agregar el widget en cuestin y un valor de la enumeracin 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 posicin fila=0, columna=0.layout->addWidget(boton1, 0, 0); layout->addWidget(boton2, 0, 1); layout->addWidget(boton3, 1, 0);

En la lnea 17 colocamos al primer botn en la celda definida por la interseccin de la fila cero con la columna cero, es decir, posicin 0,0. Luego colocamos al boton2 y boton3 en las celdas 0,1 y 1,1 respectivamente. El espacio vaco en la celda 1,0 se genera debido a que el QGridLayout crea tantas divisiones de filas y columnas como el nmero mximo 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 aadieramos los botones al layout mediante las lneaslayout->addWidget(boton1, 0, 0); layout->addWidget(boton2, 1, 1); layout->addWidget(boton3, 2, 2);

Obtendramos el siguiente resultado:

Sin embargo habr que tener en cuenta que las filas o columnas extras no sern visibles a menos que establezcamos el alto/ancho mnimo 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 automticamente el alto/ancho mnimo de esta fila/columna con un valor igual al mnimo requerido por el widget en cuestin. Podemos establecer el ancho mnimo de una columna y el alto mnimo de una fila con las funciones:setColumnMinimumWidth(int columna, int anchoMinimo ) setRowMinimumHeight(int fila, int altoMinimo)

Por ejemplo si aadieramos los botones al layout mediante el siguiente cdigo:layout->addWidget(boton1, 0, 0); layout->addWidget(boton2, 1, 1); layout->addWidget(boton3, 3, 3);

Se crearan cuatro filas y cuatro columnas, es decir, una fila y columna ms que en el ejemplo anterior, pero al ejecutar el programa obtendramos el mismo resultado que se muestra en la imagen pasada. Esto ocurre debido a que aunque la fila y columna con el nmero dos existen, estas tienen un alto y ancho de cero ya que no hemos colocado ningn widget en ellas ni hemos establecido el tamao mnimo para ellas. Pero si despus de la lnea dnde agregamos el ltimo botn al layout aadimos las lneas:layout->setColumnMinimumWidth(2, 60); layout->setRowMinimumHeight(2, 20);

Obtendramos el siguiente resultado:

QFormLayout. Organizar los Widgets a Manera de FormularioEl 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 cdigo para crear una aplicacin con un layout como el de la imagen anterior es el siguiente:1. 2. 3. 4. 5. 6. #include #include #include #include #include

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

9.

10.

QApplication app(argc, argv); QDialog ventana; QFormLayout *layout QPushButton *boton1 QPushButton *boton2 QPushButton *boton3

11. 12. 13. 14. 15. 17. 18. 19. 21. 22.

= = = =

new new new new

QFormLayout(&ventana); QPushButton(QObject::trUtf8("Botn 1")); QPushButton(QObject::trUtf8("Botn 2")); QPushButton(QObject::trUtf8("Botn 3"));

16. layout->addRow(QObject::trUtf8("Botn 1:"), boton1); layout->addRow(QObject::trUtf8("Botn 2:"), boton2); layout->addRow(QObject::trUtf8("Botn 3:"), boton3); ventana.setWindowTitle("QVBoxLayout"); ventana.show();

20.

23.

24.

25.

return app.exec(); }

En este caso nuestro layout ser del tipo QFormLayout y para aadir widgets utilizarermos la funcinaddRow(QLabel *etiqueta, QWidget *widget)

aunque tambin es posible utilizar la siguiente funcin sobre cargada, con el fin de evitar que nosotros tengamos que crear una etiqueta para cada uno de los widgets que deseeemos agregar:addRow(const QString &texto, QWidget *widget)

17. 18. 19.

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

En las lneas 17 a 19 agregamos los widgets al layout, utilizamos la versin sobrecargada de addRow() en la que el primer parmetro es una cadena de texto con el fin de ahorrar cdigo, 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 creacin de formularios para la solicitud de informacin (como un registro de usuarios o un formulario de comentarios) en dnde debemos de indicar que informacin debe de capturar el usuario en cada campo.

Layouts Anidados. Interfaces de Usuario Complejas en QtNormalmente las aplicaciones que desarrollemos no tendrn una interfaz tan sencilla como para ser diseadas utilizando slo un layout, para organizar los widgets de maneras ms complejas utilizamos layouts anidados, es decir, un layout dentro de otro. La funcin que nos permite anidar layouts depende del tipo de layout que estemos utilizando, para QHBoxLayout y QVBoxLayout la funcin es:addLayout(QLayout *layout, int Qt::Alignment align=0)

Para el QGridLayout adems debemos especificar la fila y columna de la celda dnde deseamos agregar el layout, de la siguiente formaaddLayout(QLayout *layout, int fila, int columna, Qt::Alignment align=0)

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

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

Est funcin recibe como parmetros 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 funcin recibe cmo parmetro un apuntador al layout que deseamos agregar. A continuacin mostraremos un sencillo ejemplo de anidacin de layouts para crear una interfaz de usuario muy conocida: un formulario de inicio de sesin.1. 2. 3. 4. 5. 6. 7. 8. #include #include #include #include #include #include #include

9. int main(int argc, char *argv[])10.

11. 13. 14. 15. 16. 17. 19. 20. 22. 23. 25. 26. 28. 29. 31. 32. 34. 35. 36. 38. 39. 40. 42. 43. 45.

12.

{ QApplication app(argc, argv); QDialog ventana; QHBoxLayout *layoutUsuario = new QHBoxLayout; QHBoxLayout *layoutContrasenia = new QHBoxLayout; QHBoxLayout *layoutBotones = new QHBoxLayout; QVBoxLayout *layoutPrincipal = new QVBoxLayout(&ventana); 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); layoutPrincipal->addLayout(layoutUsuario); layoutPrincipal->addLayout(layoutContrasenia); layoutPrincipal->addLayout(layoutBotones); ventana.setWindowTitle(QObject::trUtf8("Iniciar Sesin")); ventana.show(); return app.exec();

18.

21.

24.

27.

30.

33.

37.

41.

44.

46.

}

Al ejecutar este cdigo obtendremos una salida parecida a la siguiente imagen

En las lneas 1 a 7 incluimos los archivos de cabecera necesarios para desarrollar la aplicacin, mientras que en las lneas 13 a 26 creamos los widgets que utilizaremos. En las lneas 28 y 29 colocamos los widgets del campo usuario en un QHBoxLayout, lo mismo hacemos para los campos de contrasea y para los botones. Con el fin de lograr una interfaz ms agradable alineamos los botones a la derecha insertando un espacio en blanco al principio del QHBoxLayout mediante la instruccinaddStretch(int stretch=0);

38. 39. 40.

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

A partir de la lnea 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 contrasea y por ltimo el que contiene los botones. Es posible disear una interfaz de usuario utilizando distintas combinaciones de layouts, es cuestin de tiempo y experiencia poder encontrar aquella que sea ms fcil y rpida de crear o la que se adapte mejor a las necesidades de nuestra aplicacin. Para el ejemplo anterior un mejor diseo (considerando que requiere menos lneas) puede lograrse utilizando un QFormLayout en lugar de los primeros dos QHBoxLayout. El cdigo es el siguiente:1. 2. 3. 4. 5. 6. 7. #include #include #include #include #include #include

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

10. 12. 13. 14. 16. 17. 19.

QApplication app(argc, argv); QDialog ventana; QHBoxLayout *layoutBotones = new QHBoxLayout; QFormLayout *layoutPrincipal = new QFormLayout(&ventana); QLineEdit *campoUsuario = new QLineEdit(); QLineEdit *campoContrasenia = new QLineEdit(); QPushButton *botonAceptar = new QPushButton("Aceptar");

11.

15.

18.

20.21.

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.setWindowTitle(QObject::trUtf8("Iniciar Sesin")); ventana.setWindowFlags(Qt::Window); ventana.show(); return app.exec(); }

22. 23. 24. 26. 27. 28. 30. 31. 32. 34.

25.

29.

33. 35.

Al ejecutar este cdigo obtenemos una salida similar a la siguiente

La cual tiene una apariencia muy similar a la del ejemplo anterior pero que luce un poco mejor en algunos aspectos, lo relevante para este ejemplo es que el nmero de lneas utilizadas se redujo un poco, y es de suponer que en una aplicacin de mayor tamao el ahorro de lneas de cdigo tambin ser mayor.

Signals y Slots. Implementando la Funcionalidad de una Aplicacin QtEn la parte anterior de este tutorial vimos como utilizar layouts para disear la interfaz grfica de nuestras aplicaciones y para ejemplificarlo diseamos un dilogo de inicio de sesin.

En esta parte del tutorial aprenderemos a implementar la funcionalidad de nuestras aplicaciones utilizando Seales y Slots, los cuales forman el mecanismo a travs del cual los objetos de una aplicacin de Qt (incluyendo widgets) se comunican. Este mecanismo es una de la caractersticas distintivas de Qt, ya que otros frameworks suelen utilizar un enfoque basado en callbacks. Una seal es una notificacin que un objeto emite cundo cambia su estado de manera que podra interesarle a otros objetos. Un slot es una funcin que se ejecuta cundo una seal se emite. Cualquier objeto en el que deseemos implementar seales y slots debe de heredar de la clase QObject, los widgets que utilizaremos normalmente cumplen con esto ya que heredan de QWidget que a su vez hereda de QObject. Los widgets que nos proporciona Qt poseen seales y slots predefinidos, pero tambin es posible crear un widget personalizado con el fin de aadir nuestras propias seales y slots. A continuacin mostramos el cdigo de nuestra aplicacin de inicio de sesin, en el cul utilizamos seales y slots para implementar su funcionalidad, esto es que al capturar un nombre de usuario registrado y su contrasea correspondiente se nos permita el acceso a una seccin restringida de una aplicacin y que al capturar un nombre de usuario no registrado o una contrasea no coincidente se niegue el acceso. En este ejemplo utilizaremos dos seales y dos slots, recordemos que las seales se emiten cundo un objeto cambia de estado de manera interesante para otros objetos, en este caso sern emitidas cuando se presione alguno de los botones; Cada una de estas seales est conectada a un slot diferente, el cual se ejecuta cuando el botn respectivo es presionado. Ms adelante veremos el cdigo de estos slots. En esta ocasin nuestra aplicacin se compone de tres archivos, un archivo de definicin de la clase, uno de implementacin y un archivo main, definimos una nueva clase debido a que necesitamos un dilogo personalizado para implementar el slot que se ejecutar cundo se presione el botn Aceptar en nuestra ventana de login, el slot que se ejecuta cuando se presiona el botn cancelar (close() el cual cierra la ventana) ya est predefinido.

NOTA: Slo revisaremos a detalle las secciones que no hayan sido explicadas en partes anteriores del tutorial o que sean relevantes para esta explicacin El contenido de login.h, el archivo de definicin de clase, es el siguiente:1. #ifndef LOGIN_H 2. #define LOGIN_H 3. 4. #include 5. 6. class QPushButton; 7. class QLineEdit; 8. 9. class Login : public QDialog 10. { 11. Q_OBJECT 12. 13.public: 14. Login(QWidget *parent=0); 15. 16.private slots: 17. void verificarDatos(); 18. 19.private: 20. QPushButton *botonAceptar, *botonCancelar; 21. QLineEdit *campoUsuario, *campoPassword; 22. }; 23. #endif // LOGIN_H #include

En la lnea 4 incluimos el archivo de cabecera de QDialog el cul necesitamos debido a que nos basaremos en l para construir nuestro dilogo.class QPushButton; class QLineEdit;

En las lneas 6 y 7 indicamos al compilador que utilizaremos las clases QPushButton y QLineEdit, pero no especificamos sus detalles, los cuales se encuentran en sus archivos .h propios, es posible hacer esto debido a que declaramos las variables como tipo apuntador y a que en este archivo slo las definimos pero no las utilizamos. Tambin hubiera sido posible incluir los archivos de cabecera pero el slo indicar el nombre de las clases permite reducir el tiempo de compilacin.class Login : public QDialog

En la lnea 9 definimos nuestra nueva clase, la cual tendr el nombre de Login y heredar de QDialog.Q_OBJECT

En la lnea 11 utilizamos una macro llamada Q_OBJECT la cual es necesaria en cada clase que utilice seales y slots. Esta macro define algunas funciones de instrospeccin utilizadas por otras funciones como connect() y es necesaria para que el cdigo de Qt sea traducido por el compilador meta objeto (moc, por sus siglas en ingls) a cdigo C++ estndar.public: Login();

A partir de la lnea 13 declalramos las funciones y los miembros de nuestra clase. En la lnea 14 declaramos el constructor de nuestra clase.void verificar();

En la lnea 17 definimos nuestro slot personalizado, el cual lleva por nombre verificarDatos(), se ejecuta cundo se presione el botn Aceptar y como su nombre lo indica se encarga de verificar que los datos ingresados sean correctos.QPushButton *botonAceptar, *botonCancelar; QLineEdit *campoUsuario, *campoPassword;

En las lneas 20 y 21 declaramos los widgets que utilizaremos en nuestra aplicacin, dos campos de texto, uno para el nombre de usuario y otro para la contrasea y dos botones, uno para solicitar la verificacin de los datos capturados y otro para salir, que slo se provee por comodidad. El contenido del archivo login.cpp es el siguiente:1. 2. 3. 4. 5. 6. 7. 8. 9. #include "login.h" #include #include #include #include #include #include

10.Login::Login(QWidget *parent) 11. : QDialog(parent)12.

13. 14. 16. 17. 19. 20. 22. 23. 24. 26. 27. 28. 30. 32. 33. 35. 36.

15.

{ QFormLayout *layoutPrincipal = new QFormLayout; QHBoxLayout *layoutBotones = new QHBoxLayout; botonAceptar = new QPushButton(trUtf8("Aceptar")); botonCancelar = new QPushButton(trUtf8("Cancelar")); campoUsuario = new QLineEdit(); campoPassword = new QLineEdit(); layoutBotones->addStretch(); layoutBotones->addWidget(botonAceptar); layoutBotones->addWidget(botonCancelar); layoutPrincipal->addRow(trUtf8("Usuario"), campoUsuario); layoutPrincipal->addRow(trUtf8("Contrasea"), campoPassword); layoutPrincipal->addRow(layoutBotones); setLayout(layoutPrincipal); connect(botonAceptar, SIGNAL(clicked()), this, SLOT(verificarDatos())); connect(botonCancelar, SIGNAL(clicked()), this, SLOT(close())); }

18.

21.

25.

29. 31.

34.

37. 38. 39.void Login::verificarDatos()

40.

{ if(campoUsuario->text() == "zonaqt" && campoPassword->text() == "zonaqt"){ QMessageBox::information(this, "", trUtf8("Bienvenido a la aplicacin")); QApplication::quit(); } else QMessageBox::warning(this, "", trUtf8("La combinacin usuario/contrasea no es vlida")); 47. }

41. 42. 43. 44. 45. 46.

#include "login.h"

En la lnea 1 incluimos el archivo de definicin de nuestra clase.Login::Login() { QFormLayout *layoutPrincipal = new QFormLayout; QHBoxLayout *layoutBotones = new QHBoxLayout; ...

En la lnea 10 comienza la implementacin del constructor de nuestra clase, en l inicializamos los widgets y layouts necesario para la aplicacin y definimos la apariencia de nuestro widget de la misma forma que hicimos en la seccin anterior del tutorial.connect(botonAceptar, SIGNAL(clicked()), this, SLOT(verificar()));

connect(botonCancelar, SIGNAL(clicked()), this, SLOT(close()));

Las lneas 30 y 31 son las que presentan novedades. En ellas utilizamos la funcin:connect(QObject *emisor, const char *signal, QObject *receptor, const char *slot, Qt::ConnectionType type=Qt::AutoConnection);

La funcin connect es la encargada de conectar o enlazar dos QObjects, recibe como parmetros un apuntador al QObject emisor de la seal de inters, un apuntador a un arreglo de caracteres que indica la firma de funcin de la seal que nos interesa monitorear, un apuntador al QObject receptor de la seal y otro apuntador a un arreglo de caracteres, esta vez con la firma de funcin del slot que se ejecutar cundo se emita la seal indicada. Las macros SIGNAL() y SLOT() son requeridas por el moc al indicar el segundo y cuarto parmetro, respectivamente. Es necesario que las firmas de las funciones indicadas en estas macros coincidan en sus parmetros. Con la excepcin de que la seal indicada puede tener ms parmetros que los requeridos por el slot, en este caso los parmetros adicionales son ignorados. Al utilizar la funcin connect() se pueden presentar los siguientes casos: Cada

seal est conectada a un slot distinto. Este es el caso ms simple y es el que mostramos en este ejemplo, en l el slot que se ejecuta depende de la seal que se emite. Ms de una seal puede estar conectada a un slot. En este caso el slot se ejecutar cundo se emita cualquiera de las seales conectadas a l. Una seal puede estar conectada a ms de un slot. En este caso todos los slots conectados a la seal en cuestin se ejecutarn cundo dicha seal se emita, uno tras otro en un orden indeterminado.

Una

seal puede estar conectada a otra seal. En este caso la seal indicada en el cuarto parmetro se emitir al emitirse la indicada en el segundo parmetro.void Login::verificar()

En la lnea 34 comienza la implementacin de nuestro slot personalizado, indicamos el tipo de dato de retorno, despus la clase a la que pertenece seguido del nombre del slot y su lista de parmetros, en este caso no ningn parmetro es requerido.if(campoUsuario->text() == "zonaqt.com" && campoPassword->text() == "zonaqt.com"){ QMessageBox::information(this, "", trUtf8("Bienvenido a la aplicacin")); emit exit(0); } else QMessageBox::warning(this, "", trUtf8("La combinacin usuario/contrasea no es vlida"));

En la lnea 36 verificamos que la informacin capturada en los campos de texto coincida con la informacin de algn usuario registrado, en este caso y para mantener la simpleza indicamos en el cdigo un nico usuario: programacion, y su contrasea correspondiente: linux. La funcin QLineEdit::text() devuelve una QString con el contenido del QLineEdit en cuestin, en este caso el nombre de usuario para campoUsuario y la contrasea para campo Password. QString es una clase de Qt que representa una cadena de caracteres unicode y que nos proporciona funciones bastante tiles como concatenacin, traduccin o bsqueda y reemplazo de caracteres, entre otras. En caso de que la informacin capturada sea correcta mostramos un mensaje de bienvenida o confirmacin y cerramos esta ventana para mostrar la ventana principal, debido a que en este momento slo tenemos una ventana entonces salimos de la aplicacin. En caso de que la informacin capturada sea incorrecta mostramos un mensaje de aviso informando que hubo un error. Los mensajes de bienvenida o error, son mostrados al usuario utilizando las funciones estticas de la clase QMessageBoxStandarButton QMessageBox::information(QWidget *padre, const QString &titulo, const QString &mensaje, StandarButtons boton=Ok, StandarButton botonPredeterminado=NoButton)

Esta funcin la utilizamos para mostrar un dilogo como el siguiente:

StandarButton QMessageBox::warning(QWidget *padre, const QString &titulo, const QString &mensaje, StandarButtons botones=Ok, StandarButton botonPredeterminado=NoButton)

Esta funcin la utilizamos para mostrar un dilogo como el siguiente: Estas funciones permiten mostrar un dilogo para mostrar informacin relevante o hacer una pregunta al usuario y recibir una respuesta. Estas funciones reciben como parmetros obligatorios: Un apuntador al QWidget padre, que en este caso es nuestra ventana de login lo cual indicamos con la instruccin this; Una cadena de texto que ser el ttulo del mensaje; Y una cadena

de texto que aparecer en el contenido del QMessageBox. Y como parmetros opcionales: Un conjunto de valores de la enumeracin StandarButtons, que representan los botones que la QMessageBox incluir y un elemento de la enumeracin StandarButtons el cual representa al botn por default de la QMessageBox, es decir, el cual cambiar su estado a presionado (emitir la seal clicked()) al presionar la tecla enter, en caso de no especificar estos parmetros se seleccionar por defecto el botn Ok. El contenido del archivo main.cpp es el siguiente1. #include 2. #include "login.h" 3. 4. int main(int argc, char *argv[]) 5. { 6. QApplication app(argc, argv); 7. 8. Login *login = new Login(); 9. 10. login->show(); 11. 12. return app.exec(); 13. } #include "login.h"

En la lnea 2 incluimos el archivo de definicin de nuestra clase Login.Login login; login.show();

Y finalmente en la lnea 8 creamos e inicializamos un objeto de nuestra clase login, el cual mostramos en la lnea 10.

QMainWindow. La ventana principal de una aplicacinEn el artculo anterior de este tutorial vimos como implementar la funcionalidad de una aplicacin grfica de Qt utilizando seales y slots. En este artculo revisaremos a detalle un widget especial, QMainWindow, el cul posee caractersticas especiales para ser utilizado como la ventana principal de las aplicaciones Qt.

La estructura de la QMainWindow se puede ver en la siguiente imagen Diagrama

Una QMainWindow puede estar compuesta de las siguientes cinco reas o secciones: Menu Bar Como su nombre lo indica esta barra contiene mens, los cuales estn compuestos por elementos de texto o etiquetas que indican las acciones que puede realizar la aplicacin y que se ejecutan al hacer clic sobre ellas. Normalmente slo existe una de ellas en la ventana y est colocada en la parte superior, debajo de la barra de ttulo. Algunos ejemplos muy conocidos de mens que suelen colocarse en esta barra son Archivo, Edicin, Herramientas o Ayuda. Toolbars Al igual que la barra de mens, esta clase de barras, conocida como barra de herramientas est compuesta por las acciones que puede realizar la aplicacin, 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 mens y podemos encontrar una o ms 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 aplicacin, las acciones que est realizando o la descripcin 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 aplicacin 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 aplicacin. Central Widget Este widget representa el rea de trabajo de una aplicacin, como la tabla de celdas de una aplicacin en hoja de clculo o el rea de texto de un procesador de textos. Podemos reconocer ests secciones en un buen nmero de aplicaciones, como ejemplo presentamos la ventana de Open Office Writer (clic para ampliar). A continuacin mostraremos un sencillo ejemplo de una aplicacin que basada en una QMainWindow, la cual contendr una etiqueta como widget central la cual cambiar el texto que muestra dependiendo de la accin que ejecutemos, estas acciones se encontrarn en una barra de mens y una barra de herramientas tambin incluiremos una barra de estatus. La aplicacin 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 definicin de las funciones que utilizaremos en esta aplicacin. ventanaprincipal.cpp es el archivo fuente de la clase VentanaPrincipal, contiene la implementacin de las funciones declaradas en el archivo de encabezado. main.cpp A continuacin revisaremos a detalle los archivos de la aplicacin, slo explicaremos las secciones que no hayan sido revisadas en partes anteriores de este tutorial o que sean relevantes en este contexto ventanaprincipal.h1. #ifndef VENTANAPRINCIPAL_H 2. #define VENTANAPRINCIPAL_H 3. 4. #include 5. 6. class QLabel; 7. class QToolBar; 8. class QAction; 9. class QMenu; 10. 11.class VentanaPrincipal : public QMainWindow 12. { 13. Q_OBJECT 14. 15.public: 16. VentanaPrincipal(QWidget *parent=0); 17. 18.private slots: 19. void accionNuevoLanzada();

20. 21. 22.

void accionAbrirLanzada(); void accionAcercaDeLanzada(); void accionSalirLanzada();

23. 24.private: 25. QMenu* menuArchivo; 26. QMenu* menuAyuda; 27. QToolBar* barraDeHerramientas; 28. QAction* accionNuevo; 29. QAction* accionAbrir; 30. QAction* accionAcercaDe; 31. QAction* accionSalir; 32. QLabel* widgetCentral; 33. }; 34. #endif

En la lnea 4 incluimos el archivo de cabecera QMainWindow el cual contiene la definicin de la clase en la que basaremos nuestra ventana principal. En la lnea 11 comenzamos con la definicin de nuestra clase VentanaPrincipal e indicamos que heredar de QMainWindow. De la lneas 18 a 22 declaramos los slots por medio de los cuales implementaremos la funcionalidad de nuestra aplicacin. Y finalmente de las lneas 24 a 32 declaramos las variables que utilizaremos en la aplicacin.1. 2. 3. 4. 5. 6. 7. 8. #include "ventanaprincipal.h" #include #include #include #include #include

9. VentanaPrincipal::VentanaPrincipal(QWidget *parent) 10. :QMainWindow(parent)11.

12. 13. 15. 17. 18. 20. 21. 22. 24. 25. 26. 28. 29. 30.

{ 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"), 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 aplicacin"));

14. 16.

19.

23.

27.

31.

32.

accionAcercaDe = new QAction(QIcon("iconos/salir.png"), trUtf8("&Acerca de"), this); 33. accionAcercaDe->setShortcut(QKeySequence("Ctrl+d")); 34. accionAcercaDe->setStatusTip(trUtf8("Informacin sobre esta aplicacin")); 35. 36. menuArchivo->addAction(accionNuevo); 37. menuArchivo->addAction(accionAbrir); 38. menuArchivo->addSeparator(); 39. menuArchivo->addAction(accionSalir); 40. 41. menuAyuda->addAction(accionAcercaDe); 42. 43. barraDeHerramientas->addAction(accionNuevo); 44. barraDeHerramientas->addAction(accionAbrir); 45. barraDeHerramientas->addSeparator(); 46. barraDeHerramientas->addAction(accionSalir); 47. 48. setCentralWidget(widgetCentral); 49. statusBar()->showMessage(trUtf8("Bienvenido")); 50. setWindowTitle("Ventana Principal"); 51. setMinimumSize(200, 200); 52. 53. connect(accionNuevo, SIGNAL(triggered()), 54. this, SLOT(accionNuevoLanzada())); 55. 56. connect(accionAbrir, SIGNAL(triggered()), 57. this, SLOT(accionAbrirLanzada())); 58. 59. connect(accionAcercaDe, SIGNAL(triggered()), 60. this, SLOT(accionAcercaDeLanzada())); 61. 62. connect(accionSalir, SIGNAL(triggered()), 63. this, SLOT(accionSalirLanzada())); 64. } 65. 66.void VentanaPrincipal::accionNuevoLanzada() 67. { 68. widgetCentral->setText(trUtf8("Accin \"Nuevo\" lanzada")); 69. this->resize(QSize(widgetCentral->sizeHint().width(), 200)); 70. } 71. 72.void VentanaPrincipal::accionAbrirLanzada() 73. { 74. widgetCentral->setText(trUtf8("Accin \"Abrir\" lanzada")); 75. this->resize(QSize(widgetCentral->sizeHint().width(), 200)); 76. } 77. 78.void VentanaPrincipal::accionAcercaDeLanzada() 79. { 80. QMessageBox::about(this, this->windowTitle(), trUtf8("Aqu se debe colocar informacin sobre la aplicacin y la compaia que la desarolla\n\nForto, tutoriales y noticias de Qt en Espaol en:\nhttp://www.zonaqt.com")); 81. } 82. 83.void VentanaPrincipal::accionSalirLanzada() 84. {

85.86.

exit(0); }

De las lneas 1 a 7 incluimos los archivos de cabecera necesarios para implementar la aplicacin. En las lnea 12 inicializamos la variable menuArchivo la cual representa un men que podemos incluir en la barra de mens de la QMainWindow, para lograrlo utilizamos las funcionesQMenuBar* QMainWindow::menuBar()

Devuelve una referencia a una barra de mens que es creada al llamar a la funcin por primera vez.QMenu* QMenuBar::addMenu(QString &texto)

Devuelve una referencia a un men que se crear al llamar a la funcin y que mostrar en pantalla el texto indicado en la cadena de caracteres que se pasa como parmetro. En la lnea 13 realizamos lo mismo para el men Ayuda. En la lnea 15 inicializamos la variable que representa a una barra de herramientas. La funcin 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 funcin y que mostrar en pantalla la cadena que se pasa como parmetro. En la lnea 17 inicializamos la etiqueta que ser utilizada como widget central en la aplicacin. Y en la lnea 18 establecemos la fuente que queremos que ocupe la etiqueta, esto se hace mediante la instruccin:QLabel::setFont(QFont(QString &fuente, int tamanio));

La cual recibe como parmetros un objeto QFont, el cual representa una fuente de texto y que a su vez recibe como parmetros el nombre de la fuente y el tamao de la misma. En la lnea 20 inicializamos nuestra variable accionNuevo, del tipo QAction, mediante el constructor de la claseQAction::QAction(QIcon(QString &archivo), QString &texto, QWidget* padre)

Este constructor recibe como parmetros un objeto QIcon, el cual representa un icono que se mostrar cuando la accin sea colocada dentro de una barra de herramientas y que a su vez recibe como parmetro una cadena de texto con la direccin dnde se encuentra el archivo de imagen que mostrar el icono, el segundo parmetro del constructor de la clase QAction es una cadena que indica el texto que se mostrar cuando la accin sea colocada dentro de una barra de mens y el ltimo parmetro es el widget padre de la accin. QAction Antes de seguir debemos definir el concepto de QAction: Una QAction es una representacin abstracta de un comando de la aplicacin 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 mens, un icono de alguna barra de

herramientas o una combinacin de teclas, por mencionar algunos ejemplos. Una QAction nos es muy til en este tipo de situacin ya que puede estar asociada a mltiples widgets, gracias a esto ser posible proporcionar la misma funcin en distintos lugares de la aplicacin y de manera sincronizada, entonces podemos decir que una QAction proporciona una interfaz comn para la ejecucin de los comandos de la aplicacin. Siguiendo con el cdigo, en la lnea 21 establecemos un atajo de teclado para nuestra accin Nuevo, mediante la funcinQAction::setShortcut(const QKeySecuence secuencia)

la cual recibe como parmetro un elemento de la enumeracin QKeySecuence, dicha enumeracin nos proporciona combinaciones estndar de teclas dependiendo de la configuracin 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 combinacin de teclas Ctrl+N sin embargo esto puede ser distinto en otro sistema operativo, pero al utilizar esta enumeracin Qt se encargar de administrarlo y en caso de que se requiera, asociarlo a otra combinacin de teclas ms adecuada en esa situacin. En la lnea 22 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 accin correspondiente. Esto se logra mediante la funcin:QAction::setStatusTip(QString &texto)

La cual recibe como parmetro una cadena con el texto que deseamos mostrar. En las lneas 24 a 34 realizamos lo mismo para las acciones restantes. En las lneas 36 a 39 agregamos tres de las acciones que creamos al men Archivo. Esto lo hacemos a travs de la funcinQMenu::addAction(QAction* accion)

Con el fin de lograr un diseod e interfaz de usuario ms claro y atractivo en la lnea 38 agregamos un separardor, utilizando la funcinQMenu::addSeparator()

Un separador es una lnea 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 categora especfica o diferente del resto de las acciones del mismo men o barra de herramientas. En la lnea 41 agregamos la accin AcercaDe al men Ayuda. En las lneas 43 a 46 agregamos las acciones a la barra de herramientas de la aplicacin utilizando las mismas funciones que utilizamos para agregarlas a los mens. En la lnea 49 creamos la barra de estatus mediante la funcin

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 lnea utilizamos la funcinQStatusBar::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 aplicacin puede comenzar a utilizarse. En las lneas 53 y 54 conectamos la accin accionNuevo con su slot correspondiente, esto lo realizamos mediante la funcin connect(), la cual revisamos a detalle en un artculo anterior. Debido a que una accin puede estar asociada a mltiples widgets no siempre ser lanzada de la misma forma, debido a ello Qt nos proporciona la seal triggered() (lanzada o disparada) la cual se emitir cada vez que un widget asociado a la seal sea activado, por ejemplo un clic sobre un botn lanzar una accin asociada al mismo mientras que una combinacin de teclas lanzar dicha accin al ser presionada por el usuario. En las lneas 56 a 63 conectamos las acciones restantes a sus respectivos slots. En la lnea 66 comienza la implementacin de los slots, los slots accionNuevoLanzada y accionAbriLanzada cambiarn el texto que se muestra en la etiqueta utilizada como widget central y redimensionarn la ventana para ajustarla al nuevo texto mostrado. El cambio de texto de la etiqueta se realiza mediante la funcinQLabel::setText(QString &texto)

la cual recibe como parmetro una cadena de caracteres con el texto que se desea mostrar. El cambio de tamao de la ventana se realiza mediante la funcinQMainWindow::resize(QSize(int width, int height))

esta funcin recibe como parmetro un objeto QSize, el cual es una estructura que incluye el ancho y alto de un widget y que a su vez recibe como parmetros dos enteros indicando el ancho y alto del widget, respectivamente. Tambin utilizamos la funcin sizeHint() la cual devuelve un objeto QSize con el tamao requerido por el widget sobre el que se llamo la funcin. En la lnea 78 comienza la implementacin del slot asociado a la accin acercaDe, en la lnea 80 indicamos que al dispararse dicha accin se mostrar el conocido dilogo acerca de el cul contiene informacin sobre la aplicacin como versino fecha de lanzamiento y sobre la compaia que creo la aplicacin. Finalmente en las lneas 83 a 86 implementamos el slot asociado a la accin salir, en la lnea 85 utilizamos la funcin exit(int codigo) para indicar que deseamos salir de la aplicacin, la aplicacin devolver un cdigo el cdigo de error indicado como parmetro. Normalmente un valor de cero indica que la aplicacin termino normalmente, es decir, sin ningn error.

main.cpp1. #include 2. #include "ventanaprincipal.h" 3. 4. int main(int argc, char *argv[]) 5. { 6. QApplication a(argc, argv); 7. VentanaPrincipal w; 8. w.show(); 9. 10. return a.exec(); 11. }

En la lnea 1 incluimos el archivo de cabecera de la clase VentanaPrincipal, mientras que en la lnea 8 creamos e inicializamos un objeto de dicha clase, y finalmente en la lnea 10 mostramos nuestra ventana principal. Al ejecutar esta aplicacin de ejemplo obtendremos algo parecido a lo mostrado en las siguientes imagenes:

Dilogos en Qt. Comunicacin con el Usuario.En esta seccin del tutorial hablaremos acerca de los dilogos, pequeas ventanas secundarias que sirven para comunicarse con el usuario. Los dilogos son tiles en ocasiones en las que requerimos la confirmacin del usuario antes de ejecutar una accin, como al guardar o eliminar un archivo o al salir de una aplicacin, tambin suelen utilizarse para obtener pequeas cantidades de informacin, como la palabra a buscar en un dilogo de buscar y reemplazar o el nombre que se desea dar a un marcador/favorito en un navegador web. Podemos utilizar dilogos de Qt de dos formas distintas, una es crendolos nosotros como lo hemos hecho en otros artculos de este tutorial y la otra es utilizar el API esttica de dilogos comnmente utilizados que nos provee Qt, entre estos dilogos se encuentran los de peticin de informacin al usuario o los de seleccin de carpetas, archivos, fuentes o colores. En esta seccin del tutorial mostramos dos ejemplos de uso de dilogos. El primero trata sobre dilogos modales y no modales y sobre como obtener el valor de una opcin seleccionada por un usuario en un dilogo. En el segundo revisamos lso dilogos estndar que ofrece Qt para obtener valores de tipo especfico como nmeros, cadenas de texto, colores, tipos de letra, nombres de archivo, etc.

Dilogos modales y no modales.En este artculo del tutorial crearemos un ejemplo de dilogos modales y no modales. Podemos mostrar un dilogo en pantalla con una de las siguientes dos funciones:void QWidget::show();

Esta funcin se hereda de QWidget y es equivalente a llamar a la funcin setVisible con un parmetro booleano con valor de true, mostrar un dilogo a travs de esta funcin es til si

queremos que el usuario pueda continuar interactuando con la ventana que mostr el dilogo, los dilogos que permiten dicha interaccin se conocen con el nombre de dilogos no modales.int QDialog::exec();

Esta funcin sirve para mostrar un dilogo modal, este es un tipo de dilogos que bloquean el acceso a las dems ventanas de la aplicacin. Mostrar un dilogo con la funcin exec() permite obtener el valor de la respuesta elegida por el usuario. A continuacin mostramos un ejemplo para observar de mejor manera la diferencia entre show y exec.

El ejemplo se compone de los siguientes archivos: dialogomodal.h dialogomodal.cpp widgetprincipal.h widgetprincipal.cpp main.cpp

La clase DialogoModal, representa un dilogo personalizado muy simple que slo muestra una etiqueta en el lugar en dnde se colocaran los widgets en un dilogo de una aplicacin real, est clase nos servir para ver cmo podemos gestionar las respuestas que puede emitir un dilogo modal.

El cdigo de la clase DialogoModal es el siguiente:

NOTA: Slo explicaremos las lneas relevantes para el ejemplo o que no hayan sido explicadas en artculos anteriores de este tutorial.

dialogomodal.h1. #ifndef DIALOGOMODAL_H 2. #define DIALOGOMODAL_H 3. 4. #include 5. 6. class QLabel; 7. class QPushButton; 8. 9. class DialogoModal : public QDialog 10. { 11. Q_OBJECT 12. public: 13. explicit DialogoModal(QWidget *parent = 0); 14. 15. private: 16. QLabel *nombre; 17. QPushButton *botonAceptar; 18. QPushButton *botonRechazar; 19. QPushButton *botonOtro; 20. 21. private slots: 22. void botoonOtroPresionado(); 23. }; 24. 25. #endif // DIALOGOMODAL_H

dialogomodal.cpp26. 27. 28. 29. 30. 31. 32. #include "dialogomodal.h" #include #include #include #include

33. DialogoModal::DialogoModal(QWidget *parent) : 34. QDialog(parent)35.

36. 37. 39. 40. 41. 42. 44. 46. 47. 48.

{

QVBoxLayout* layoutPrincipal = new QVBoxLayout; QHBoxLayout* layoutBotones = new QHBoxLayout; nombre = new QLabel(trUtf8("Dilogo Modal")); botonAceptar = new QPushButton(trUtf8("Aceptar")); botonRechazar = new QPushButton(trUtf8("Rechazar")); botonOtro = new QPushButton(trUtf8("Otro")); nombre->setFont(QFont("Sans-Serif", 15)); layoutBotones->addStretch(); layoutBotones->addWidget(botonAceptar); layoutBotones->addWidget(botonRechazar);

38.

43. 45.

49.50.

layoutBotones->addWidget(botonOtro); layoutPrincipal->addWidget(nombre); layoutPrincipal->addLayout(layoutBotones); setLayout(layoutPrincipal);

51. 52. 54. 56. 57. 58.

53. 55.

connect(botonAceptar, SIGNAL(clicked()), this, SLOT(accept())); connect(botonRechazar, SIGNAL(clicked()), this, SLOT(reject())); connect(botonOtro, SIGNAL(clicked()), this, SLOT(botonOtroPresionado())); 59. } 60. 61. void DialogoModal::botonOtroPresionado() { 62. done(42); 63. }

Explicaremos slo la implementacin de esta clase, es decir, el archivo cpp. De la lnea 14 a la 17 creamos los widgets que componen nuestro dilogo. Los botones botonAceptar, botonRechazar y botonOtro representan las distintas opciones con las que el usuario puede responder al mensaje en el dilogo. De las lneas 31 a 33 conectamos la seal clicked() de los botones al slot correspondiente con la accin que queremos que realicen. Los botones botonAceptar y botonRechazar se conectan a los slots accept() y reject(), los cules estn previamente definidos en QDialog y se encargan de ocultar el dilogo y devolver el cdigo respuesta correspondiente, 1 para accept (aceptar) y 0 para reject (rechazar), como valor de retorno de la funcin exec. Por otra parte el botn de nombre botonOtro se conecta a un slot botonOtroPresionado el cul es implementado por nosotros. Dicha implementacin comienza en la lnea 36 y en realidad es slo una envoltura para llamar al slot:QDialog::done(int r)

El cual tambin es parte de QDialog, este slot nos permite hacer algo similar a accept() y reject(), es decir, ocultar el dilogo y enviar un cdigo de respuesta, con la diferencia de que en done() podemos especificar el cdigo de respuesta que queremos enviar. En este caso enviamos el nmero 42, pero puede ser cualquier otro entero. El cdigo de la clase WidgetPrincipal es el siguiente:

widgetprincipal.h64. 65. 66. 67. 68. #ifndef WIDGETPRINCIPAL_H #define WIDGETPRINCIPAL_H #include

69. class QDialog;

70. class QLabel; 71. class QPushButton; 72. class DialogoModal;73. 75.

74. class WidgetPrincipal : public QWidget 76. Q_OBJECT 77. public: 78. explicit WidgetPrincipal(QWidget *parent = 0);79. 81. {

80. signals: 82. private: 83. QPushButton *botonDialogoModal; 84. QPushButton *botonDialogoNoModal; 85. QLabel *resultadoDialogoModal; 86. QDialog *dialogoNoModal; 87. DialogoModal *dialogoModal;88.

89. private slots: 90. void ejecutar();91. 92. 93. }; #endif // WIDGETPRINCIPAL_H

widgetprincipal.cpp94. 95. 96. 97. 98. 99. 100. 101. 102. #include "dialogomodal.h" #include "widgetprincipal.h" #include #include #include #include #include

103. 104. 106. 108.

105. 107.

WidgetPrincipal::WidgetPrincipal(QWidget *parent) : QWidget(parent) { QGridLayout* layoutPrincipal = new QGridLayout;

botonDialogoModal = new QPushButton(QObject::trUtf8("Mostrar Dilogo Modal")); 109. botonDialogoNoModal = new QPushButton(QObject::trUtf8("Mostrar Dilogo No Modal")); 110. 111. resultadoDialogoModal = new QLabel("\t\t"); 112. 113. dialogoModal = new DialogoModal; 114. dialogoNoModal = new QDialog(this); 115. 116. resultadoDialogoModal->setFrameStyle(1); 117. 118. layoutPrincipal->addWidget(botonDialogoModal, 0, 0); 119. layoutPrincipal->addWidget(resultadoDialogoModal, 0, 1); 120. layoutPrincipal->addWidget(botonDialogoNoModal, 1, 0); 121.

122. 123. 124.125.

setLayout(layoutPrincipal); setWindowFlags(Qt::Window); setWindowTitle(trUtf8("Dilogos Personalizados"));

126.

connect(botonDialogoModal, SIGNAL(clicked()), this, SLOT(ejecutar())); 127. connect(botonDialogoNoModal, SIGNAL(clicked()), dialogoNoModal, SLOT(show())); 128. connect(this, SIGNAL(rejected()), this, SLOT(QApplication::exit())); 129. } 130. 131. void WidgetPrincipal::ejecutar() { 132. int respuesta = dialogoModal->exec(); 133. 134. QMessageBox::information(this, "", QString::number(respuesta)); 135. 136. switch(respuesta) { 137. case 0: 138. resultadoDialogoModal->setText(trUtf8("Rechazar presionado")); 139. break; 140. 141. case 1: 142. resultadoDialogoModal->setText(trUtf8("Aceptar presionado")); 143. break; 144. 145. default: 146. resultadoDialogoModal->setText(trUtf8("Otro presionado")); 147. break; 148. } 149. }

Explicaremos slo la implementacin de esta clase, es decir, el archivo cpp. De las lneas 15 a 21 creamos los widgets que componen nuestra widget. En la lnea 18 creamos una etiqueta que mostrar la respuesta de nuestro dilogo modal y le indicamos que muestre dos tabuladores como texto para que tenga un tamao mnimo que pueda contener la respuesta del dilogo, esto es slo por motivos estticos. En la lnea 21 creamos un dilogo que utilizaremos como dilogo no modal e indicamos que nuestra clase WidgetPrincipal ser su padre, esto provocar que el dilogo no modal se muestre centrado respecto a la posicin de nuestro widget; Este comportamiento no lo observamos para nuestro dilogo modal creado en la lnea 20 ya que no hemos establecido un padre para l.

En la lnea 23 establecemos un estilo de lnea para el borde/marco de la etiqueta que mostrar la respuesta del dilogo modal. De las lneas 33 a 35 realizamos las conexiones de seales y slots. La seal rejected() tambin se emite cundo se usa el botn cerrar de la barra de ttulo de un dilogo. En las lneas 33 y 34 conectamos la seal clicked de los botones a los slots que mostrarn el dilogo correspondiente, modal o no modal, el dilogo no modal lo mostramos llamando directamente a show debido a que esta funcin no devuelve ningn cdigo de respuesta que tengamos que gestionar. En la lnea 35 conectamos la seal, rejected() de nuestra ventana al QApplication::exit(), el cual har que termine nuestra aplicacin. El dilogo modal lo mostramos en el slot ejecutar(), implementado por nosotros a partir de la lnea 38 y asignamos su resultado a una variable, despus procesamos el valor de este resultado, en este caso comparamos dicho valor con los cdigos de resultado usuales y el que definimos nosotros, dependiendo de con que valor coincida modificamos el valor de la etiqueta resultadoDialogoModal.

Es todo en la primera parte de este artculo, en la siguiente parte continuaremos con el tema de los dilogos; Mostraremos la otra forma de obtener informacin de parte del usuario: Utilizando los dilogos estndar de Qt.

Dialogos Estndar de Qt

En el artculo anterior revisamos la primera de las dos formas principales de utilizar dilogos en Qt, esto es creando clases que hereden de QDialog, implementando la funcionalidad de estas clases y gestionando las respuestas que recibimos a travs de la funcin QDialog::exec() En este artculo veremos la segunda forma de utilizar dilogos en una aplicacin de Qt, esto es, utilizando las clases de dilogos estndar que nos proporciona Qt, estas clases son: QMessageBox

Permite mostrar mensajes de notificacin al usuario. QFileDialog Permite mostrar un dilogo que sirve para seleccionar un archivo o carpeta del sistema de archivos. QInputDialog Permite mostrar un dilogo con un widget para que el usuario puede introducir informacin. QColorDialog Muestra un dilogo para que el usuario pueda seleccionar un color. QPrintDialog Muestra un dilogo para especificar configuraciones de la impresora. Para este artculo utilizaremos la aplicacin de ejemplo "Standard Dialogs" de la documentacin oficial de Qt la cual est disponible en el sitio web de Qt y desde la seccin Help de Qt Creator. Este ejemplo se compone de los siguientes archivos: dialogo.h dialogo.cpp main.cpp

Los archivos dialogo.h y ventana.cpp componen la clase Dialogo, la cual representa el widget principal de la aplicacin 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 dilogo estndar que nos permitir obtener un dato del usuario. La segunda columna se compone de etiquetas y en cada una de ellas escribiremos la informacin que proporcion el usuario a travs del dilogo correspondientes. Esta ventana se muestra en la siguiente imagen.

El cdigo de la clase Dilogo es el siguiente:

dialogo.h1. #ifndef DIALOG_H 2. #define DIALOG_H 3. 4. #include 5. 6. class QCheckBox; 7. class QLabel; 8. class QErrorMessage; 9. 10.class Dialogo : public QDialog 11. { 12. Q_OBJECT 13. 14.public: 15. Dialogo(QWidget *parent = 0); 16. 17.private slots: 18. void setInteger(); 19. void setDouble(); 20. void setItem(); 21. void setText(); 22. void setColor();

23. 24. 25. 26. 27. 28. 29. 30. 31. 32.

void void void void void void void void void void

setFont(); setExistingDirectory(); setOpenFileName(); setOpenFileNames(); setSaveFileName(); criticalMessage(); informationMessage(); questionMessage(); warningMessage(); errorMessage();

33. 34.private: 35. QCheckBox *native; 36. QLabel *integerLabel; 37. QLabel *doubleLabel; 38. QLabel *itemLabel; 39. QLabel *textLabel; 40. QLabel *colorLabel; 41. QLabel *fontLabel; 42. QLabel *directoryLabel; 43. QLabel *openFileNameLabel; 44. QLabel *openFileNamesLabel; 45. QLabel *saveFileNameLabel; 46. QLabel *criticalLabel; 47. QLabel *informationLabel; 48. QLabel *questionLabel; 49. QLabel *warningLabel; 50. QLabel *errorLabel; 51. QErrorMessage *errorMessageDialog; 52. 53. QString openFilesPath; 54. };

dialogo.cpp1. #include 2. #include 3. #include 4. #include 5. #include 6. #include 7. #include 8. #include 9. #include 10. 11. #include "dialogo.h" 12. 13. #define MESSAGE \ 14. Dialogo::tr("Message boxes have a caption, a text, " \ 15. "and any number of buttons, each with standard or custom texts." \ 16. "Click a button to close the message box. Pressing the Esc button " \ 17. "will activate the detected escape button (if any).") 18. 19.Dialogo::Dialogo(QWidget *parent) 20. : QDialog(parent)

21.

22. 24. 26. 27. 28. 29. 31. 32. 33. 34. 36. 37. 38. 40. 41. 42. 44. 45. 46. 48. 49. 50. 52. 53. 54. 55. 57. 58. 59. 60. 62. 63. 64. 65. 67. 68. 69. 70. 72. 73. 74. 75.

23. 25.

{ errorMessageDialog = new QErrorMessage(this); int frameStyle = QFrame::Sunken | QFrame::Panel; integerLabel = new QLabel; integerLabel->setFrameStyle(frameStyle); QPushButton *integerButton = new QPushButton(tr("QInputDialog::get&Int()")); doubleLabel = new QLabel; doubleLabel->setFrameStyle(frameStyle); QPushButton *doubleButton = new QPushButton(tr("QInputDialog::get&Double()")); itemLabel = new QLabel; itemLabel->setFrameStyle(frameStyle); QPushButton *itemButton = new QPushButton(tr("QInputDialog::getIte&m()")); textLabel = new QLabel; textLabel->setFrameStyle(frameStyle); QPushButton *textButton = new QPushButton(tr("QInputDialog::get&Text()")); colorLabel = new QLabel; colorLabel->setFrameStyle(frameStyle); QPushButton *colorButton = new QPushButton(tr("QColorDialog::get&Color()")); fontLabel = new QLabel; fontLabel->setFrameStyle(frameStyle); QPushButton *fontButton = new QPushButton(tr("QFontDialog::get&Font()")); directoryLabel = new QLabel; directoryLabel->setFrameStyle(frameStyle); QPushButton *directoryButton = new QPushButton(tr("QFileDialog::getE&xistingDirectory()")); openFileNameLabel = new QLabel; openFileNameLabel->setFrameStyle(frameStyle); QPushButton *openFileNameButton = new QPushButton(tr("QFileDialog::get&OpenFileName()")); openFileNamesLabel = new QLabel; openFileNamesLabel->setFrameStyle(frameStyle); QPushButton *openFileNamesButton = new QPushButton(tr("QFileDialog::&getOpenFileNames()")); saveFileNameLabel = new QLabel; saveFileNameLabel->setFrameStyle(frameStyle); QPushButton *saveFileNameButton = new QPushButton(tr("QFileDialog::get&SaveFileName()")); criticalLabel = new QLabel; criticalLabel->setFrameStyle(frameStyle); QPushButton *criticalButton = new QPushButton(tr("QMessageBox::critica&l()"));

30.

35.

39.

43.

47.

51.

56.

61.

66.

71.

76.

77. 78. 79. 80.81.

informationLabel = new QLabel; informationLabel->setFrameStyle(frameStyle); QPushButton *informationButton = new QPushButton(tr("QMessageBox::i&nformation()")); questionLabel = new QLabel; questionLabel->setFrameStyle(frameStyle); QPushButton *questionButton = new QPushButton(tr("QMessageBox::&question()")); warningLabel = new QLabel; warningLabel->setFrameStyle(frameStyle); QPushButton *warningButton = new QPushButton(tr("QMessageBox::&warning()")); errorLabel = new QLabel; errorLabel->setFrameStyle(frameStyle); QPushButton *errorButton = new QPushButton(tr("QErrorMessage::showM&essage()"));

82. 83. 84. 85. 87. 88. 89. 91. 92. 93. 94.

86.

90.

95.

96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110.

connect(integerButton, SIGNAL(clicked()), this, SLOT(setInteger())); connect(doubleButton, SIGNAL(clicked()), this, SLOT(setDouble())); connect(itemButton, SIGNAL(clicked()), this, SLOT(setItem())); connect(textButton, SIGNAL(clicked()), this, SLOT(setText())); connect(colorButton, SIGNAL(clicked()), this, SLOT(setColor())); connect(fontButton, SIGNAL(clicked()), this, SLOT(setFont())); connect(directoryButton, SIGNAL(clicked()), this, SLOT(setExistingDirectory())); connect(openFileNameButton, SIGNAL(clicked()), this, SLOT(setOpenFileName())); connect(openFileNamesButton, SIGNAL(clicked()), this, SLOT(setOpenFileNames())); connect(saveFileNameButton, SIGNAL(clicked()), this, SLOT(setSaveFileName())); connect(criticalButton, SIGNAL(clicked()), this, SLOT(criticalMessage())); 111. connect(informationButton, SIGNAL(clicked()), 112. this, SLOT(informationMessage())); 113. connect(questionButton, SIGNAL(clicked()), this, SLOT(questionMessage())); 114. connect(warningButton, SIGNAL(clicked()), this, SLOT(warningMessage())); 115. connect(errorButton, SIGNAL(clicked()), this, SLOT(errorMessage())); 116. 117. native = new QCheckBox(this); 118. native->setText("Use native file dialog."); 119. native->setChecked(true); 120. QGridLayout *layout = new QGridLayout; 121. layout->setColumnStretch(1, 1); 122. layout->setColumnMinimumWidth(1, 250); 123. layout->addWidget(integerButton, 0, 0); 124. layout->addWidget(integerLabel, 0, 1); 125. layout->addWidget(doubleButton, 1, 0); 126. layout->addWidget(doubleLabel, 1, 1); 127. layout->addWidget(itemButton, 2, 0); 128. layout->addWidget(itemLabel, 2, 1);

129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154.155.

layout->addWidget(textButton, 3, 0); layout->addWidget(textLabel, 3, 1); layout->addWidget(colorButton, 4, 0); layout->addWidget(colorLabel, 4, 1); layout->addWidget(fontButton, 5, 0); layout->addWidget(fontLabel, 5, 1); layout->addWidget(directoryButton, 6, 0); layout->addWidget(directoryLabel, 6, 1); layout->addWidget(openFileNameButton, 7, 0); layout->addWidget(openFileNameLabel, 7, 1); layout->addWidget(openFileNamesButton, 8, 0); layout->addWidget(openFileNamesLabel, 8, 1); layout->addWidget(saveFileNameButton, 9, 0); layout->addWidget(saveFileNameLabel, 9, 1); layout->addWidget(criticalButton, 10, 0); layout->addWidget(criticalLabel, 10, 1); layout->addWidget(informationButton, 11, 0); layout->addWidget(informationLabel, 11, 1); layout->addWidget(questionButton, 12, 0); layout->addWidget(questionLabel, 12, 1); layout->addWidget(warningButton, 13, 0); layout->addWidget(warningLabel, 13, 1); layout->addWidget(errorButton, 14, 0); layout->addWidget(errorLabel, 14, 1); layout->addWidget(native, 15, 0); setLayout(layout); } setWindowTitle(tr("Standard Dialogs"));

156. 159. 161. 162. 163. 164. 165. 168.

157. 158. 160.

166. 167. 169.

void Dialogo::setInteger() { bool ok; int i = QInputDialog::getInt(this, tr("QInputDialog::getInteger()"), tr("Percentage:"), 25, 0, 100, 1, &ok); if (ok) integerLabel->setText(tr("%1%").arg(i)); }

void Dialogo::setDouble() { 170. bool ok; 171. double d = QInputDialog::getDouble(this, tr("QInputDialog::getDouble()"), 172. tr("Amount:"), 37.56, -10000, 10000, 2, &ok); 173. if (ok) 174. doubleLabel->setText(QString("$%1").arg(d)); 175. } 176. 177. void Dialogo::setItem() 178. { 179. QStringList items; 180. items setText(color.name()); 209. colorLabel->setPalette(QPalette(color)); 210. colorLabel->setAutoFillBackground(true); 211. } 212. } 213. 214. void Dialogo::setFont() 215. { 216. bool ok; 217. QFont font = QFontDialog::getFont(&ok, QFont(fontLabel->text()), this); 218. if (ok) { 219. fontLabel->setText(font.key()); 220. fontLabel->setFont(font); 221. } 222. } 223. 224. void Dialogo::setExistingDirectory() 225. { 226. QFileDialog::Options options = QFileDialog::DontResolveSymlinks | QFileDialog::ShowDirsOnly; 227. if (!native->isChecked()) 228. options |= QFileDialog::DontUseNativeDialog; 229. QString directory = QFileDialog::getExistingDirectory(this, 230. tr("QFileDialog::getExistingDirectory()"), 231. directoryLabel->text(), 232. options);

233. 234.235. 236. }

if (!directory.isEmpty()) directoryLabel->setText(directory); void Dialogo::setOpenFileName() { QFileDialog::Options options; if (!native->isChecked()) options |= QFileDialog::DontUseNativeDialog; QString selectedFilter; QString fileName = QFileDialog::getOpenFileName(this, tr("QFileDialog::getOpenFileName()"), openFileNameLabel->text(), tr("All Files (*);;Text Files (*.txt)"), &selectedFilter, options); if (!fileName.isEmpty()) openFileNameLabel->setText(fileName); }

237. 239. 240. 241. 242. 243. 244. 245. 246. 247. 248. 249. 250. 253.

238.

251. 252. 254.

void Dialogo::setOpenFileNames() { 255. QFileDialog::Options options; 256. if (!native->isChecked()) 257. options |= QFileDialog::DontUseNativeDialog; 258. QString selectedFilter; 259. QStringList files = QFileDialog::getOpenFileNames( 260. this, tr("QFileDialog::getOpenFileNames()"), 261. openFilesPath, 262. tr("All Files (*);;Text Files (*.txt)"), 263. &selectedFilter, 264. options); 265. if (files.count()) { 266. openFilesPath = files[0]; 267. openFileNamesLabel->setText(QString("[%1]").arg(files.join(", "))); 268. } 269. } 270. 271. void Dialogo::setSaveFileName() 272. { 273. QFileDialog::Options options; 274. if (!native->isChecked()) 275. options |= QFileDialog::DontUseNativeDialog; 276. QString selectedFilter; 277. QString fileName = QFileDialog::getSaveFileName(this, 278. tr("QFileDialog::getSaveFileName()"), 279. saveFileNameLabel->text(), 280. tr("All Files (*);;Text Files (*.txt)"), 281. &selectedFilter, 282. options); 283. if (!fileName.isEmpty()) 284. saveFileNameLabel->setText(fileName); 285. } 286.

287.

void Dialogo::criticalMessage() { 289. QMessageBox::StandardButton reply; 290. reply = QMessageBox::critical(this, tr("QMessageBox::critical()"), 291. MESSAGE, 292. QMessageBox::Abort | QMessageBox::Retry | QMessageBox::Ignore); 293. if (reply == QMessageBox::Abort) 294. criticalLabel->setText(tr("Abort")); 295. else if (reply == QMessageBox::Retry) 296. criticalLabel->setText(tr("Retry")); 297. else 298. criticalLabel->setText(tr("Ignore")); 299. } 300. 301. void Dialogo::informationMessage() 302. { 303. QMessageBox::StandardButton reply; 304. reply = QMessageBox::information(this, tr("QMessageBox::information()"), MESSAGE); 305. if (reply == QMessageBox::Ok) 306. informationLabel->setText(tr("OK")); 307. else 308. informationLabel->setText(tr("Escape")); 309. } 310. 311. void Dialogo::questionMessage() 312. { 313. QMessageBox::StandardButton reply; 314. reply = QMessageBox::question(this, tr("QMessageBox::question()"), 315. MESSAGE, 316. QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); 317. if (reply == QMessageBox::Yes) 318. questionLabel->setText(tr("Yes")); 319. else if (reply == QMessageBox::No) 320. questionLabel->setText(tr("No")); 321. else 322. questionLabel->setText(tr("Cancel")); 323. } 324. 325. void Dialogo::warningMessage() 326. { 327. QMessageBox msgBox(QMessageBox::Warning, tr("QMessageBox::warning()"), 328. MESSAGE, 0, this); 329. msgBox.addButton(tr("Save &Again"), QMessageBox::AcceptRole); 330. msgBox.addButton(tr("&Continue"), QMessageBox::RejectRole); 331. if (msgBox.exec() == QMessageBox::AcceptRole) 332. warningLabel->setText(tr("Save Again")); 333. else 334. warningLabel->setText(tr("Continue")); 335. 336. } 337. 338. void Dialogo::errorMessage() 339. { 288.

340. 341. 342. 343. 344. 345. 346. 347. 348.349. }

errorMessageDialog->showMessage( tr("This dialog shows and remembers error messages. " "If the checkbox is checked (as it is by default), " "the shown message will be shown again, " "but if the user unchecks the box the message " "will not appear again if QErrorMessage::showMessage() " "is called with the same message.")); errorLabel->setText(tr("If the box is unchecked, the message " "won't appear again."));

A continuacin explicaremos el cdigo de la implementacin de nuestra clase Dialogo, es decir, el archivo cpp. El cdigo es largo, pero muchas cosas se repiten, as que la explicacin se acorta bastante. De las lneas 1 a 12 incluimos los archivos de cabecera que necesitamos para este ejemplo. En la lnea 20 comienza el constructor de nuestra clase. En la lnea 23 creamos un objeto de la clase QErrorMessage el cual provee un dilogo para mostrar un mensaje de error. En la lnea 25 obtenemos el valor de la opcin que indica el estilo que queremos dar a la etiqueta. De la lnea 27 a la 95 creamos los botones y las etiquetas que contendr el dilogo y establecemos el texto y opciones para cada uno de estos widgets. De la lnea 97 a la lnea 116 realizamos las conexiones de cada uno de los botones con su slot correspondiente. En seguida explicaremos el cdigo de cada uno de estos slots. De la lnea 121 a la 155 creamos el layout principal de nuestro widget y organizamos los widgets de acuerdo a l. El la lnea 160 comienza la implementacin de los slots de nuestro dilogo, en todos ellos realizamos las siguiente acciones: Creamos

una variable para almacenar la informacin que ingresa el usuario por medio del dilogo. Ejecutamos el dilogo para obtener la informacin del usuario y el valor de respuesta, este ltimo est determinado por el botn que presiona el usuario. Evaluamos el valor de respuesta del dilogo. Dependiendo del valor de la respuesta decidimos de que manera procesar la informacin capturada, si es que la hay. Si el usuario no cierra el dilogo y en cambio presiona algn botn, entonces escribimos el valor de la respuesta en la etiqueta correspondiente. Comenzaremos con los slots que hacen uso de los dilogos que nos ofrece la clase QInputDialog. De la lnea 160 a la 167 implementamos el slot setInteger, en l mostramos un dilogo que contiene una spinBox que permitir al usuario establecer un valor numrico entero. Este dilogo lo ejecutamos mediante la funcin

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 parmetros de est familia de funciones y de algunos de los otros dilogos estndar son iguales, indican el widget padre, el ttulo del dilogo, el texto que se mostrar en el dilogo, un apuntador a la variable donde se almacenar la respuesta al dilogo y una lista de flags u opciones del dilogo. A partir del cuarto parmetro y .en orden, los parmetros especficos de este dilogo son: El

valor predeterminado que al que se establecer la spinbox cuando se muestre el dilogo. El valor mnimo al que se puede establecer el valor de la spinbox. El valor mximo 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 lneas 169 a 176 implementamos el slot setDouble, en l mostramos un dilogo muy similar al que del slot obtenerEntero con la diferencia de que el valor de la spinbox podr ser un valor decimal o de punto flotante de doble precisin. Este dilogo lo ejecutamos mediante la funcindouble 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 parmetros de esta funcin son muy similares a la funcin getInt salvo por el sptimo parmetro, el cul indica el nmero de decimales del nmero, el valor por defecto es de uno. De la lnea 178 a 188 implementamos el slot obtenerElemento, en l mostramos un dilogo que contiene una combobox que permite al usuario elegir un valor de una lista que indiquemos. Este dilogo lo ejecutamos mediante la funcinQString 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 funcin recibe del cuarto al sexto parmetro: Una

lista de cadenas de texto que sern los elementos de la combobox. La posicin del elemento seleccionado por defecto, si no se especifica ser cero. Un valor booleano que indica si la combobox ser editable. De las lneas 190 a 198 implementamos el slot setText, en l mostramos un dilogo que nos permitir obtener un valor de texto capturado por el usuario. Este dilogo lo ejecutamos mediante la funcinQString 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 funcin recibe como cuarto y quinto parmetro: El

modo (EchoMode) en el que se mostrar el texto ingresado. Aqui podemos establecer un valor de la enumeracin EchoMode el cual indicar si el texto debe ser visible, que no se muestre o que se muestren caracteres para enmascarar contraseas (como asteriscos) El valor predeterminado que se mostrar en el campo de texto De las lneas 200 a 213 implementamos el slot setColor, en l mostramos un dilogo que contiene controles especializados para permitir que el usuario eliga un color. Este dilogo lo mostramos mediante la funcinQColorDialog::getColor( const QColor & initial, QWidget * parent, const QString & title, ColorDialogOptions options = 0 )

Esta funcin recibe como parmetros: Un

objeto de la clase QColor que indica el color inicial que se establecer en el dilogo, si no se especifica n