GettingstartedSpanish: Difference between revisions
No edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
[[Category:Spanish]] | [[Category:Spanish]] | ||
h1. Introducción a la Programación con Qt | |||
Bienvenido al mundo de Qt — el toolkit multiplataforma para GUI. En esta guía de iniciación, aprenderemos conceptos básicos de Qt mediante la implementación de una simple aplicación de Bloc de Notas. Al terminar de leer esta guía, usted debería estar listo para ahondar en nuestras descripciones técnicas generales y en la documentación de nuestra API, para poder encontrar la información que necesite sobre la aplicación que esté desarrollando. | Bienvenido al mundo de Qt — el toolkit multiplataforma para GUI. En esta guía de iniciación, aprenderemos conceptos básicos de Qt mediante la implementación de una simple aplicación de Bloc de Notas. Al terminar de leer esta guía, usted debería estar listo para ahondar en nuestras descripciones técnicas generales y en la documentación de nuestra API, para poder encontrar la información que necesite sobre la aplicación que esté desarrollando. | ||
Line 5: | Line 6: | ||
== Hola Bloc de Notas == | == Hola Bloc de Notas == | ||
En este primer ejemplo, simplemente creamos y mostramos en el escritorio, un editor de texto dentro de un marco de ventana. | En este primer ejemplo, simplemente creamos y mostramos en el escritorio, un editor de texto dentro de un marco de ventana. | ||
Esto representa el programa más simple posible de Qt que posea GUI. | |||
[[Image:http://doc.qt.nokia.com/4.7/images/gs1.png|http://doc.qt.nokia.com/4.7/images/gs1.png]] | [[Image:http://doc.qt.nokia.com/4.7/images/gs1.png|http://doc.qt.nokia.com/4.7/images/gs1.png]] | ||
Este es el código: | Este es el código: | ||
<code>#include <QApplication> | |||
#include <QTextEdit> | |||
int main(int argv, char **args) | int main(int argv, char **args) | ||
{ | |||
QApplication app(argv, args); | |||
QTextEdit textEdit; | QTextEdit textEdit; | ||
textEdit.show(); | |||
return app.exec | return app.exec(); | ||
}</code> | |||
Revisemos el código línea por línea. En las primeras dos líneas, incluimos los archivos de cabecera de | Revisemos el código línea por línea. En las primeras dos líneas, incluimos los archivos de cabecera de "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html y "QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html, las cuales son las dos clases que necesitamos para este ejemplo. Todas las clases de Qt tienen un archivo de cabecera que lleva su nombre. | ||
En la línea 6 creamos un objeto de la clase | En la línea 6 creamos un objeto de la clase "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html. Este objeto maneja los recursos de la aplicación y es necesario para ejecutar cualquier programa de Qt que tenga GUI. Necesita '''argv''' y '''argc''' debido a que Qt acepta algunos argumentos de la línea de comandos. | ||
En la línea 8 creamos un objeto de la clase | En la línea 8 creamos un objeto de la clase "QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html. Un editor de texto es un elemento visual en la interfaz gráfica. En Qt, estos elementos se conocen con el nombre de widgets. Otros ejemplos de widgets son: barras de desplazamiento, etiquetas, y botones de radio. Un widget también puede ser un contenedor para otros widgets; un diálogo o la ventana principal de una aplicación, por ejemplo. | ||
En la línea 9 mostramos el editor de texto en la pantalla en su propio marco de ventana. Debido a que los widgets también funcionan como contenedores (por ejemplo una | En la línea 9 mostramos el editor de texto en la pantalla en su propio marco de ventana. Debido a que los widgets también funcionan como contenedores (por ejemplo una "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html, la cual tiene barras de herramientas, menus, una barra de estatus, y algunos otros widgets), es posible mostrar un solo widget en su propia ventana. Los widgets no son visibles por defecto, la función show() hace visibles los widgets. | ||
En la línea 11 la | En la línea 11 la "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html entra en su ciclo de eventos. Cuando una aplicación de Qt se está ejecutando, los eventos se generan en, y se envían a los widgets de la aplicación. Algunos ejemplos de eventos son presionar algún botón del mouse y pulsar alguna tecla. Cuando usted escribe texto en el widget editor de texto, este recibe eventos de tecla presionada y responde dibujando el texto tecleado. | ||
Para ejecutar la aplicación, ejecute una terminal, y entre al directorio en el cual tiene el archivo .cpp del programa. Los siguientes comandos de shell construyen el programa. | Para ejecutar la aplicación, ejecute una terminal, y entre al directorio en el cual tiene el archivo .cpp del programa. Los siguientes comandos de shell construyen el programa. | ||
<code> qmake -project | |||
qmake | |||
make</code> | |||
Esto generará un ejecutable en el directorio part1 (note que en Windows, posiblemente tenga que utilizar nmake en lugar de make. Note, que el ejecutable estará localizado en part1/debug o part1/release). | |||
Qmake es la herramienta de construcción de proyectos de Qt, el cual, utiliza un archivo de configuración. Qmake genera este archivo por nosotros cuando le enviamos el argumento '''-project*. Dado el archivo de configuración (con el sufijo .pro), qmake produce un archivo make el cual, construirá el programa por usted. Más adelante veremos como escribir nuestros propios archivos .pro | |||
h3. Aprender Más | |||
* Widgets y Geometría de Ventanas- "Widgets Diálogo y Ventana":http://doc.qt.nokia.com/4.7/application-windows.html | |||
''' Eventos y manejo de eventos- "El Sistema de Eventos":http://doc.qt.nokia.com/4.7/eventsandfilters.html | |||
== Agregando un botón de Salir == | == Agregando un botón de Salir == | ||
En una aplicación real, normalmente necesitará más de un widget. Vamos ahora a agregar un | En una aplicación real, normalmente necesitará más de un widget. Vamos ahora a agregar un "QPushButton":http://doc.qt.nokia.com/4.7/qpushbutton.html debajo del editor de texto. El botón hará que la aplicación Bloc de Notas finalice cuando sea pulsado (por ejemplo, si se le da click con el ratón). | ||
[[Image:http://doc.qt.nokia.com/4.7/images/gs2.png|http://doc.qt.nokia.com/4.7/images/gs2.png]] | [[Image:http://doc.qt.nokia.com/4.7/images/gs2.png|http://doc.qt.nokia.com/4.7/images/gs2.png]] | ||
Revisemos el código. | Revisemos el código. | ||
<code>#include <QtGui> | |||
int main(int argv, char **args) | int main(int argv, char **args) | ||
{ | |||
QApplication app(argv, args); | |||
QTextEdit textEdit; | QTextEdit textEdit; | ||
QPushButton quitButton("Salir"); | |||
QObject::connect(&quitButton, SIGNAL (clicked()), qApp, SLOT (quit())); | QObject::connect(&quitButton, SIGNAL (clicked()), qApp, SLOT (quit())); | ||
QVBoxLayout layout; | QVBoxLayout layout; | ||
layout.addWidget(&textEdit); | |||
layout.addWidget(&quitButton); | |||
QWidget window; | QWidget window; | ||
window.setLayout(&layout); | |||
window.show(); | window.show(); | ||
return app.exec | return app.exec(); | ||
}</code> | |||
La línea 1 incluye el archivo de cabecera | La línea 1 incluye el archivo de cabecera "QtGui":http://doc.qt.nokia.com/4.7/qtgui.html, el cual contiene todas las clases de GUI de Qt. | ||
La línea 10 utiliza el mecanismo de '''Señales''' y '''Slots''' de Qt para hacer que la aplicación termine cuando el '''botón Quit''' sea presionado. Un '''slot''' es una función que puede ser invocada en tiempo de ejecución utilizando su nombre (como una cadena de caracteres literal). Una '''señal''' es una función que invoca a los slots registrados con ella, cuando es llamada; Invocamos eso para conectar el slot con la señal y emitir la señal. | La línea 10 utiliza el mecanismo de '''Señales''' y '''Slots''' de Qt para hacer que la aplicación termine cuando el '''botón Quit''' sea presionado. Un '''slot''' es una función que puede ser invocada en tiempo de ejecución utilizando su nombre (como una cadena de caracteres literal). Una '''señal''' es una función que invoca a los slots registrados con ella, cuando es llamada; Invocamos eso para conectar el slot con la señal y emitir la señal. | ||
"quit()":http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit es un slot de "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html que termina la aplicación. "clicked()":http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked es una señal que "QPushButton":http://doc.qt.nokia.com/4.7/qpushbutton.html emite cuando es pulsado. La función estática "QObject::connect()":http://doc.qt.nokia.com/4.7/qobject.html#connect se encarga de conectar el slot a la señal. SIGNAL() y SLOT() son dos macros que reciben la firma de las funciones señal y slot a conectar. También necesitamos enviar apuntadores a los objetos que deben enviar y recibir la señal. | |||
En la línea 12 creamos un | En la línea 12 creamos un "QVBoxLayout":http://doc.qt.nokia.com/4.7/qvboxlayout.html. Como mencionamos, los widgets pueden contener otros widgets. Es posible establecer los límites (la localización y el tamaño) de los widgets hijos directamente, pero usualmente es más sencillo utilizar un layout. Un layout administra los límites de los widgets hijos. "QVBoxLayout":http://doc.qt.nokia.com/4.7/qvboxlayout.html, por ejemplo, coloca los hijos en una fila vertical. | ||
Las líneas 13 y 14 agregan el editor de texto y el botón al layout. En la línea 17, establecemos el layout sobre el widget. | Las líneas 13 y 14 agregan el editor de texto y el botón al layout. En la línea 17, establecemos el layout sobre el widget. | ||
Line 66: | Line 90: | ||
=== Aprender Más === | === Aprender Más === | ||
* Señales y slots - | * Señales y slots - "Señales & Slots":http://doc.qt.nokia.com/4.7/signalsandslots.html | ||
* Layouts - | * Layouts - "Administración de Layout":http://doc.qt.nokia.com/4.7/layout.html, "Widgets y Layouts":http://doc.qt.nokia.com/4.7/widgets-and-layouts.html, "Ejemplos de Layout":http://doc.qt.nokia.com/4.7/examples-layouts.html | ||
* Los widgets que se incluyen en Qt - | * Los widgets que se incluyen en Qt - "Galería de Widgets de Qt":http://doc.qt.nokia.com/4.7/gallery.html, "Ejemplos de Widgets":http://doc.qt.nokia.com/4.7/examples-widgets.html | ||
== Crear Una Subclase de QWidget == | == Crear Una Subclase de QWidget == | ||
Line 76: | Line 100: | ||
[[Image:http://doc.qt.nokia.com/4.7/images/gs3.png|http://doc.qt.nokia.com/4.7/images/gs3.png]] | [[Image:http://doc.qt.nokia.com/4.7/images/gs3.png|http://doc.qt.nokia.com/4.7/images/gs3.png]] | ||
Revisemos el código: | Revisemos el código: | ||
<code>class Notepad : public QWidget | |||
{ | |||
Q_OBJECT | |||
public: | public: | ||
Notepad(); | |||
private slots: | private slots: | ||
void quit(); | |||
private: | private: | ||
QTextEdit *textEdit; | |||
QPushButton *quitButton; | |||
};</code> | |||
La macro Q_OBJECT debe estar primero en la definición de la clase, y declara nuestra clase como un QObject (Naturalmente, también debe de heredar de | La macro Q_OBJECT debe estar primero en la definición de la clase, y declara nuestra clase como un QObject (Naturalmente, también debe de heredar de "QObject":http://doc.qt.nokia.com/4.7/qobject.html). Un "QObject":http://doc.qt.nokia.com/4.7/qobject.html añade varias habilidades a una clase normal de C++. Notablemente, el nombre de la clase y los nombres de los slots pueden ser consultados en tiempo de ejecución. También es posible consultar el tipo de los parámetros de un slot e invocarlo. | ||
La línea 13 declara el '''slot quit()'''. Esto es sencillo utilizando la marco '''slots'''. El '''slot quit(''') ahora puede conectarse a las '''señales''' que coincidan en su firma (cualquier señal que no reciba parámetros). | La línea 13 declara el '''slot quit()'''. Esto es sencillo utilizando la marco '''slots'''. El '''slot quit(''') ahora puede conectarse a las '''señales''' que coincidan en su firma (cualquier señal que no reciba parámetros). | ||
Line 90: | Line 122: | ||
En lugar de configurar la interfaz gráfica y conectar el slot en la función main(), ahora utilizamos el contructor del Bloc de Notas. | En lugar de configurar la interfaz gráfica y conectar el slot en la función main(), ahora utilizamos el contructor del Bloc de Notas. | ||
<code>Notepad::Notepad() | <code>Notepad::Notepad() | ||
{ | |||
textEdit = new QTextEdit; | |||
quitButton = new QPushButton(tr("Salir")); | |||
connect(quitButton, SIGNAL (clicked()), this, SLOT (quit())); | connect(quitButton, SIGNAL (clicked()), this, SLOT (quit())); | ||
QVBoxLayout '''layout = new QVBoxLayout; | QVBoxLayout '''layout = new QVBoxLayout; | ||
layout->addWidget(textEdit); | |||
layout->addWidget(quitButton); | |||
setLayout(layout); | |||
setWindowTitle(tr("Bloc de Notas")); | |||
}</code> | |||
Como se puede ver en la definición de la clase, utilizamos apuntadores (punteros) a nuestros "QObject":http://doc.qt.nokia.com/4.7/qobject.htmls (textEdit y quitButton) Como regla, usted siempre debe reservar memoria para "QObject":http://doc.qt.nokia.com/4.7/qobject.htmls en el heap y nunca copiarlos. | |||
Ahora utilizamos la función "tr()":http://doc.qt.nokia.com/4.7/qobject.html#tr alrededor de las cadenas de texto que serán visibles por el usuario. Esta función es necesaria cuando usted desea proveer su aplicación en más de un lenguaje (ejemplo, Inglés y Chino) No entraremos en detalles aquí, pero puede consultar el enlace Qt Linguist de la tabla de aprenda más. | |||
h3. Aprender Más | |||
''' tr() e internacionalización - "Manual Qt Linguist":http://doc.qt.nokia.com/4.7/linguist-manual.html, "Escribiendo Código Fuente Para Traducción":http://doc.qt.nokia.com/4.7/i18n-source-translation.html, "Ejemplo Hola tr()":http://doc.qt.nokia.com/4.7/linguist-hellotr.html, "Internacionalización con Qt":http://doc.qt.nokia.com/4.7/internationalization.html | |||
* "QObjects":http://doc.qt.nokia.com/4.7/qtwebkit-bridge.html#qobjects y el Modelo de Objetos de Qt (Esto es esencial para entender Qt) - "Modelo de Objetos":http://doc.qt.nokia.com/4.7/object.html | |||
* qmake y el sistema de construcción de Qt - "Manual qmake":http://doc.qt.nokia.com/4.7/qmake-manual.html | |||
== Creando un archivo .pro == | == Creando un archivo .pro == | ||
Para este ejemplo escribiremos nuestro archivo en lugar de utilizar la opción de qmake | Para este ejemplo escribiremos nuestro archivo en lugar de utilizar la opción de qmake -project | ||
<code> HEADERS = notepad.h | |||
SOURCES = notepad.cpp main.cpp</code> | |||
Los siguientes comandos de shell construyen el ejemplo | |||
<code> qmake | |||
make | |||
</code> | |||
h2. Usando una QMainWindow | |||
Muchas aplicaciones se beneficiarán del uso de un "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html, la cual tiene su propio layout al cual puede agregar una barra de menús, widgets de acoplamiento, barras de herramientas, y una barra de estado. "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html tiene un área central que puede ser ocupada por cualquier tipo de widget. En nuestro caso, vamos a ubicar nuestro editor de texto aquí. | |||
[[Image:http://doc.qt.nokia.com/4.7/images/gs4.png|http://doc.qt.nokia.com/4.7/images/gs4.png]] | |||
Revisemos la nueva definición de la clase Bloc de Notas (Notepad) | |||
<code>#include <QtGui> | |||
class Notepad : public QMainWindow | |||
{ | |||
Q_OBJECT | |||
public: | |||
Notepad(); | |||
private slots: | |||
void open(); | |||
void save(); | |||
void quit(); | |||
private: | |||
QTextEdit *textEdit; | |||
QAction *openAction; | |||
QAction *saveAction; | |||
QAction *exitAction; | |||
QMenu *fileMenu; | |||
};</code> | |||
Incluimos dos '''slots''' más que pueden guardar y abrir un documento. Implementaremos su funcionalidad en la siguiente sección. | |||
A menudo, en una ventana principal, el mismo '''slot''' debe ser invocado por varios widgets. Ejemplos de ello son los elementos de menú y los botones en una barra de herramientas. Para hacer esto más fácil, Qt proporciona "QAction":http://doc.qt.nokia.com/4.7/qaction.html, que puede ser dada a varios widgets, y ser conectada a un slot. Por ejemplo, tanto "QMenu":http://doc.qt.nokia.com/4.7/qmenu.html como "QToolBar":http://doc.qt.nokia.com/4.7/qtoolbar.html pueden crear elementos de menú y botones de herramientas de las mismas "QAction":http://doc.qt.nokia.com/4.7/qaction.htmls. En breve vamos a ver como funciona esto. | |||
Como antes, usamos el constructor del Bloc de Notas (Notepad) para configurar la GUI. | |||
<code>Notepad::Notepad() | |||
{ | |||
saveAction = new QAction(tr("&Open"), this); | |||
saveAction = new QAction(tr("&Save"), this); | |||
exitAction = new QAction(tr("E&amp;xit"), this); | |||
connect(openAction, SIGNAL (triggered()), this, SLOT (open())); | |||
connect(saveAction, SIGNAL (triggered()), this, SLOT (save())); | |||
connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit())); | |||
fileMenu = menuBar()->addMenu(tr("&File")); | |||
fileMenu->addAction(openAction); | |||
fileMenu->addAction(saveAction); | |||
fileMenu->addSeparator(); | |||
fileMenu->addAction(exitAction); | |||
textEdit = new QTextEdit; | |||
setCentralWidget(textEdit); | |||
setWindowTitle(tr("Notepad")); | |||
}</code> | |||
Las "QAction":http://doc.qt.nokia.com/4.7/qaction.htmls son creadas con el texto que debe aparecer en los widgets a los que las adicionemos (en nuestro caso, los elementos de menú). Si también quisieramos añadirlos a una barra de herramientas, podríamos haberles dado "iconos":http://doc.qt.nokia.com/4.7/qaction.html a las acciones. | |||
Cuando un elemento de menú es presionado, el elemento dispara la acción, y el respectivo slot se invocará. | Cuando un elemento de menú es presionado, el elemento dispara la acción, y el respectivo slot se invocará. | ||
Line 135: | Line 226: | ||
=== Aprender Más === | === Aprender Más === | ||
* Main windows y clases main window - | * Main windows y clases main window - "Aplicación Main Window":http://doc.qt.nokia.com/4.7/mainwindow.html, "Ejemplos Main Window":http://doc.qt.nokia.com/4.7/examples-mainwindow.html | ||
* Aplicaciones MDI - | * Aplicaciones MDI - "QMdiArea":http://doc.qt.nokia.com/4.7/qmdiarea.html, "Ejemplo MDI":http://doc.qt.nokia.com/4.7/mainwindows-mdi.html | ||
== Guardando y Cargando == | == Guardando y Cargando == | ||
Line 146: | Line 237: | ||
Vamos a iniciar con el '''slot open()''': | Vamos a iniciar con el '''slot open()''': | ||
<code>QString fileName = QFileDialog::getOpenFileName(this, tr( | <code>QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", | ||
tr("Text Files ('''.txt);;C++ Files ('''.cpp '''.h)")); | |||
if (fileName != "") { | |||
QFile file(fileName); | |||
if (!file.open(QIODevice::ReadOnly)) { | |||
QMessageBox::critical(this, tr("Error"), | |||
tr("Could not open file")); | |||
return; | |||
} | |||
QString contents = file.readAll().constData(); | |||
textEdit->setPlainText(contents); | |||
file.close(); | |||
}</code> | |||
El primer paso es preguntar al usuario por el nombre del archivo a abrir. Qt viene con "QFileDialog":http://doc.qt.nokia.com/4.7/qfiledialog.html, éste es un diálogo con el cual el usuario puede seleccionar un archivo. La siguiente imagen muestra el diálogo en Kubuntu. La funcion estática (static) "getOpenFileName()":http://doc.qt.nokia.com/4.7/qfiledialog.html#getOpenFileName muestra un diálogo de archivos modales, y no retorna hasta que el usuario ha seleccionado un archivo. Éste retorna la ruta del archivo seleccionado, o una cadena de texto (string) vacía si el usuario cancela el diálogo. | |||
Si tenemos un nombre de archivo, tratamos de abrirlo con "open()":http://doc.qt.nokia.com/4.7/qiodevice.html#open, que devuelve verdadero (true) si el archivo se puede abrir. No vamos a entrar en el manejo de errores aquí, pero puede consultar los enlaces de la sección aprender más. Si el archivo no se puede abrir, utilizamos "QMessageBox":http://doc.qt.nokia.com/4.7/qmessagebox.html para mostrar un diálogo con un mensaje de error (consulte la descripción de la clase "QMessageBox":http://doc.qt.nokia.com/4.7/qmessagebox.html para más detalles). | |||
En realidad, la lectura de los datos es trivial utilizando la función "readAll()":http://doc.qt.nokia.com/4.7/qiodevice.html#readAll, la cual devuelve todos los datos del archivo en un "QByteArray":http://doc.qt.nokia.com/4.7/qbytearray.html. La función "constData()":http://doc.qt.nokia.com/4.7/qbytearray.html#constData devuelve todos los datos del arreglo (array) como un const char''', "QString":http://doc.qt.nokia.com/4.7/qstring.html tiene un constructor para éste. Los contenidos se pueden visualizar en el editor de texto. Luego llamamos la función "close()":http://doc.qt.nokia.com/4.7/qiodevice.html#close que cierra el archivo para retornar la descripción del archivo al sistema operativo. | |||
Ahora, vamos a pasar al slot save(). | Ahora, vamos a pasar al slot save(). | ||
<code>QString fileName = QFileDialog::getSaveFileName(this, tr( | <code>QString fileName = QFileDialog::getSaveFileName(this, tr("Guardar archivo"), "", | ||
tr("Archivos de texto ('''.txt);;Archivos de C++ ('''.cpp '''.h)")); | |||
if (fileName != "") { | |||
QFile file(fileName); | |||
if (!file.open(QIODevice::WriteOnly)) { | |||
// mensaje de error | |||
} else { | |||
QTextStream stream(&file); | |||
stream << textEdit->toPlainText(); | |||
stream.flush(); | |||
file.close(); | |||
} | |||
}</code> | |||
Cuando escribimos el contenido del editor de texto en el archivo, utillizamos la clase "QTextStream":http://doc.qt.nokia.com/4.7/qtextstream.html, que envuelve al objeto "QFile":http://doc.qt.nokia.com/4.7/qfile.html. El flujo de texto puede escribir QStrings directamente al archivo; "QFile":http://doc.qt.nokia.com/4.7/qfile.html sólo acepta los datos en bruto (char''') con las funciones "write()":http://doc.qt.nokia.com/4.7/qiodevice.html#write de "QIODevice":http://doc.qt.nokia.com/4.7/qiodevice.html. | |||
=== Aprender Más === | === Aprender Más === |
Revision as of 10:34, 25 February 2015
h1. Introducción a la Programación con Qt
Bienvenido al mundo de Qt — el toolkit multiplataforma para GUI. En esta guía de iniciación, aprenderemos conceptos básicos de Qt mediante la implementación de una simple aplicación de Bloc de Notas. Al terminar de leer esta guía, usted debería estar listo para ahondar en nuestras descripciones técnicas generales y en la documentación de nuestra API, para poder encontrar la información que necesite sobre la aplicación que esté desarrollando.
Hola Bloc de Notas
En este primer ejemplo, simplemente creamos y mostramos en el escritorio, un editor de texto dentro de un marco de ventana. Esto representa el programa más simple posible de Qt que posea GUI.
http://doc.qt.nokia.com/4.7/images/gs1.png
Este es el código:
#include <QApplication>
#include <QTextEdit>
int main(int argv, char **args)
{
QApplication app(argv, args);
QTextEdit textEdit;
textEdit.show();
return app.exec();
}
Revisemos el código línea por línea. En las primeras dos líneas, incluimos los archivos de cabecera de "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html y "QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html, las cuales son las dos clases que necesitamos para este ejemplo. Todas las clases de Qt tienen un archivo de cabecera que lleva su nombre.
En la línea 6 creamos un objeto de la clase "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html. Este objeto maneja los recursos de la aplicación y es necesario para ejecutar cualquier programa de Qt que tenga GUI. Necesita argv y argc debido a que Qt acepta algunos argumentos de la línea de comandos.
En la línea 8 creamos un objeto de la clase "QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html. Un editor de texto es un elemento visual en la interfaz gráfica. En Qt, estos elementos se conocen con el nombre de widgets. Otros ejemplos de widgets son: barras de desplazamiento, etiquetas, y botones de radio. Un widget también puede ser un contenedor para otros widgets; un diálogo o la ventana principal de una aplicación, por ejemplo.
En la línea 9 mostramos el editor de texto en la pantalla en su propio marco de ventana. Debido a que los widgets también funcionan como contenedores (por ejemplo una "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html, la cual tiene barras de herramientas, menus, una barra de estatus, y algunos otros widgets), es posible mostrar un solo widget en su propia ventana. Los widgets no son visibles por defecto, la función show() hace visibles los widgets.
En la línea 11 la "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html entra en su ciclo de eventos. Cuando una aplicación de Qt se está ejecutando, los eventos se generan en, y se envían a los widgets de la aplicación. Algunos ejemplos de eventos son presionar algún botón del mouse y pulsar alguna tecla. Cuando usted escribe texto en el widget editor de texto, este recibe eventos de tecla presionada y responde dibujando el texto tecleado.
Para ejecutar la aplicación, ejecute una terminal, y entre al directorio en el cual tiene el archivo .cpp del programa. Los siguientes comandos de shell construyen el programa.
qmake -project
qmake
make
Esto generará un ejecutable en el directorio part1 (note que en Windows, posiblemente tenga que utilizar nmake en lugar de make. Note, que el ejecutable estará localizado en part1/debug o part1/release). Qmake es la herramienta de construcción de proyectos de Qt, el cual, utiliza un archivo de configuración. Qmake genera este archivo por nosotros cuando le enviamos el argumento -project*. Dado el archivo de configuración (con el sufijo .pro), qmake produce un archivo make el cual, construirá el programa por usted. Más adelante veremos como escribir nuestros propios archivos .pro
h3. Aprender Más
- Widgets y Geometría de Ventanas- "Widgets Diálogo y Ventana":http://doc.qt.nokia.com/4.7/application-windows.html
Eventos y manejo de eventos- "El Sistema de Eventos":http://doc.qt.nokia.com/4.7/eventsandfilters.html
Agregando un botón de Salir
En una aplicación real, normalmente necesitará más de un widget. Vamos ahora a agregar un "QPushButton":http://doc.qt.nokia.com/4.7/qpushbutton.html debajo del editor de texto. El botón hará que la aplicación Bloc de Notas finalice cuando sea pulsado (por ejemplo, si se le da click con el ratón).
http://doc.qt.nokia.com/4.7/images/gs2.png
Revisemos el código.
#include <QtGui>
int main(int argv, char **args)
{
QApplication app(argv, args);
QTextEdit textEdit;
QPushButton quitButton("Salir");
QObject::connect(&quitButton, SIGNAL (clicked()), qApp, SLOT (quit()));
QVBoxLayout layout;
layout.addWidget(&textEdit);
layout.addWidget(&quitButton);
QWidget window;
window.setLayout(&layout);
window.show();
return app.exec();
}
La línea 1 incluye el archivo de cabecera "QtGui":http://doc.qt.nokia.com/4.7/qtgui.html, el cual contiene todas las clases de GUI de Qt.
La línea 10 utiliza el mecanismo de Señales y Slots de Qt para hacer que la aplicación termine cuando el botón Quit sea presionado. Un slot es una función que puede ser invocada en tiempo de ejecución utilizando su nombre (como una cadena de caracteres literal). Una señal es una función que invoca a los slots registrados con ella, cuando es llamada; Invocamos eso para conectar el slot con la señal y emitir la señal.
"quit()":http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit es un slot de "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html que termina la aplicación. "clicked()":http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked es una señal que "QPushButton":http://doc.qt.nokia.com/4.7/qpushbutton.html emite cuando es pulsado. La función estática "QObject::connect()":http://doc.qt.nokia.com/4.7/qobject.html#connect se encarga de conectar el slot a la señal. SIGNAL() y SLOT() son dos macros que reciben la firma de las funciones señal y slot a conectar. También necesitamos enviar apuntadores a los objetos que deben enviar y recibir la señal.
En la línea 12 creamos un "QVBoxLayout":http://doc.qt.nokia.com/4.7/qvboxlayout.html. Como mencionamos, los widgets pueden contener otros widgets. Es posible establecer los límites (la localización y el tamaño) de los widgets hijos directamente, pero usualmente es más sencillo utilizar un layout. Un layout administra los límites de los widgets hijos. "QVBoxLayout":http://doc.qt.nokia.com/4.7/qvboxlayout.html, por ejemplo, coloca los hijos en una fila vertical.
Las líneas 13 y 14 agregan el editor de texto y el botón al layout. En la línea 17, establecemos el layout sobre el widget.
Aprender Más
- Señales y slots - "Señales & Slots":http://doc.qt.nokia.com/4.7/signalsandslots.html
- Layouts - "Administración de Layout":http://doc.qt.nokia.com/4.7/layout.html, "Widgets y Layouts":http://doc.qt.nokia.com/4.7/widgets-and-layouts.html, "Ejemplos de Layout":http://doc.qt.nokia.com/4.7/examples-layouts.html
- Los widgets que se incluyen en Qt - "Galería de Widgets de Qt":http://doc.qt.nokia.com/4.7/gallery.html, "Ejemplos de Widgets":http://doc.qt.nokia.com/4.7/examples-widgets.html
Crear Una Subclase de QWidget
Cuando el usuario quiere salir de una aplicación, es muy normal mostrar un diálogo que le pregunte sobre si de verdad desea salir. En este ejemplo, crearemos una subclase de QWidget, y agregaremos un slot que conectaremos al botón Salir.
http://doc.qt.nokia.com/4.7/images/gs3.png
Revisemos el código:
class Notepad : public QWidget
{
Q_OBJECT
public:
Notepad();
private slots:
void quit();
private:
QTextEdit *textEdit;
QPushButton *quitButton;
};
La macro Q_OBJECT debe estar primero en la definición de la clase, y declara nuestra clase como un QObject (Naturalmente, también debe de heredar de "QObject":http://doc.qt.nokia.com/4.7/qobject.html). Un "QObject":http://doc.qt.nokia.com/4.7/qobject.html añade varias habilidades a una clase normal de C++. Notablemente, el nombre de la clase y los nombres de los slots pueden ser consultados en tiempo de ejecución. También es posible consultar el tipo de los parámetros de un slot e invocarlo.
La línea 13 declara el slot quit(). Esto es sencillo utilizando la marco slots. El slot quit() ahora puede conectarse a las señales que coincidan en su firma (cualquier señal que no reciba parámetros).
En lugar de configurar la interfaz gráfica y conectar el slot en la función main(), ahora utilizamos el contructor del Bloc de Notas.
Notepad::Notepad()
{
textEdit = new QTextEdit;
quitButton = new QPushButton(tr("Salir"));
connect(quitButton, SIGNAL (clicked()), this, SLOT (quit()));
QVBoxLayout '''layout = new QVBoxLayout;
layout->addWidget(textEdit);
layout->addWidget(quitButton);
setLayout(layout);
setWindowTitle(tr("Bloc de Notas"));
}
Como se puede ver en la definición de la clase, utilizamos apuntadores (punteros) a nuestros "QObject":http://doc.qt.nokia.com/4.7/qobject.htmls (textEdit y quitButton) Como regla, usted siempre debe reservar memoria para "QObject":http://doc.qt.nokia.com/4.7/qobject.htmls en el heap y nunca copiarlos.
Ahora utilizamos la función "tr()":http://doc.qt.nokia.com/4.7/qobject.html#tr alrededor de las cadenas de texto que serán visibles por el usuario. Esta función es necesaria cuando usted desea proveer su aplicación en más de un lenguaje (ejemplo, Inglés y Chino) No entraremos en detalles aquí, pero puede consultar el enlace Qt Linguist de la tabla de aprenda más.
h3. Aprender Más
tr() e internacionalización - "Manual Qt Linguist":http://doc.qt.nokia.com/4.7/linguist-manual.html, "Escribiendo Código Fuente Para Traducción":http://doc.qt.nokia.com/4.7/i18n-source-translation.html, "Ejemplo Hola tr()":http://doc.qt.nokia.com/4.7/linguist-hellotr.html, "Internacionalización con Qt":http://doc.qt.nokia.com/4.7/internationalization.html
- "QObjects":http://doc.qt.nokia.com/4.7/qtwebkit-bridge.html#qobjects y el Modelo de Objetos de Qt (Esto es esencial para entender Qt) - "Modelo de Objetos":http://doc.qt.nokia.com/4.7/object.html
- qmake y el sistema de construcción de Qt - "Manual qmake":http://doc.qt.nokia.com/4.7/qmake-manual.html
Creando un archivo .pro
Para este ejemplo escribiremos nuestro archivo en lugar de utilizar la opción de qmake -project
HEADERS = notepad.h
SOURCES = notepad.cpp main.cpp
Los siguientes comandos de shell construyen el ejemplo
qmake
make
h2. Usando una QMainWindow
Muchas aplicaciones se beneficiarán del uso de un "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html, la cual tiene su propio layout al cual puede agregar una barra de menús, widgets de acoplamiento, barras de herramientas, y una barra de estado. "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html tiene un área central que puede ser ocupada por cualquier tipo de widget. En nuestro caso, vamos a ubicar nuestro editor de texto aquí.
http://doc.qt.nokia.com/4.7/images/gs4.png
Revisemos la nueva definición de la clase Bloc de Notas (Notepad)
#include <QtGui>
class Notepad : public QMainWindow
{
Q_OBJECT
public:
Notepad();
private slots:
void open();
void save();
void quit();
private:
QTextEdit *textEdit;
QAction *openAction;
QAction *saveAction;
QAction *exitAction;
QMenu *fileMenu;
};
Incluimos dos slots más que pueden guardar y abrir un documento. Implementaremos su funcionalidad en la siguiente sección.
A menudo, en una ventana principal, el mismo slot debe ser invocado por varios widgets. Ejemplos de ello son los elementos de menú y los botones en una barra de herramientas. Para hacer esto más fácil, Qt proporciona "QAction":http://doc.qt.nokia.com/4.7/qaction.html, que puede ser dada a varios widgets, y ser conectada a un slot. Por ejemplo, tanto "QMenu":http://doc.qt.nokia.com/4.7/qmenu.html como "QToolBar":http://doc.qt.nokia.com/4.7/qtoolbar.html pueden crear elementos de menú y botones de herramientas de las mismas "QAction":http://doc.qt.nokia.com/4.7/qaction.htmls. En breve vamos a ver como funciona esto.
Como antes, usamos el constructor del Bloc de Notas (Notepad) para configurar la GUI.
Notepad::Notepad()
{
saveAction = new QAction(tr("&Open"), this);
saveAction = new QAction(tr("&Save"), this);
exitAction = new QAction(tr("E&amp;xit"), this);
connect(openAction, SIGNAL (triggered()), this, SLOT (open()));
connect(saveAction, SIGNAL (triggered()), this, SLOT (save()));
connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit()));
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(openAction);
fileMenu->addAction(saveAction);
fileMenu->addSeparator();
fileMenu->addAction(exitAction);
textEdit = new QTextEdit;
setCentralWidget(textEdit);
setWindowTitle(tr("Notepad"));
}
Las "QAction":http://doc.qt.nokia.com/4.7/qaction.htmls son creadas con el texto que debe aparecer en los widgets a los que las adicionemos (en nuestro caso, los elementos de menú). Si también quisieramos añadirlos a una barra de herramientas, podríamos haberles dado "iconos":http://doc.qt.nokia.com/4.7/qaction.html a las acciones.
Cuando un elemento de menú es presionado, el elemento dispara la acción, y el respectivo slot se invocará.
Aprender Más
- Main windows y clases main window - "Aplicación Main Window":http://doc.qt.nokia.com/4.7/mainwindow.html, "Ejemplos Main Window":http://doc.qt.nokia.com/4.7/examples-mainwindow.html
- Aplicaciones MDI - "QMdiArea":http://doc.qt.nokia.com/4.7/qmdiarea.html, "Ejemplo MDI":http://doc.qt.nokia.com/4.7/mainwindows-mdi.html
Guardando y Cargando
En este ejemplo, vamos a implementar la funcionalidad de los slots open() y save() que adicionamos en el ejemplo anterior.
http://doc.qt.nokia.com/4.7/images/gs5.png
Vamos a iniciar con el slot open():
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "",
tr("Text Files ('''.txt);;C++ Files ('''.cpp '''.h)"));
if (fileName != "") {
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
QMessageBox::critical(this, tr("Error"),
tr("Could not open file"));
return;
}
QString contents = file.readAll().constData();
textEdit->setPlainText(contents);
file.close();
}
El primer paso es preguntar al usuario por el nombre del archivo a abrir. Qt viene con "QFileDialog":http://doc.qt.nokia.com/4.7/qfiledialog.html, éste es un diálogo con el cual el usuario puede seleccionar un archivo. La siguiente imagen muestra el diálogo en Kubuntu. La funcion estática (static) "getOpenFileName()":http://doc.qt.nokia.com/4.7/qfiledialog.html#getOpenFileName muestra un diálogo de archivos modales, y no retorna hasta que el usuario ha seleccionado un archivo. Éste retorna la ruta del archivo seleccionado, o una cadena de texto (string) vacía si el usuario cancela el diálogo.
Si tenemos un nombre de archivo, tratamos de abrirlo con "open()":http://doc.qt.nokia.com/4.7/qiodevice.html#open, que devuelve verdadero (true) si el archivo se puede abrir. No vamos a entrar en el manejo de errores aquí, pero puede consultar los enlaces de la sección aprender más. Si el archivo no se puede abrir, utilizamos "QMessageBox":http://doc.qt.nokia.com/4.7/qmessagebox.html para mostrar un diálogo con un mensaje de error (consulte la descripción de la clase "QMessageBox":http://doc.qt.nokia.com/4.7/qmessagebox.html para más detalles).
En realidad, la lectura de los datos es trivial utilizando la función "readAll()":http://doc.qt.nokia.com/4.7/qiodevice.html#readAll, la cual devuelve todos los datos del archivo en un "QByteArray":http://doc.qt.nokia.com/4.7/qbytearray.html. La función "constData()":http://doc.qt.nokia.com/4.7/qbytearray.html#constData devuelve todos los datos del arreglo (array) como un const char, "QString":http://doc.qt.nokia.com/4.7/qstring.html tiene un constructor para éste. Los contenidos se pueden visualizar en el editor de texto. Luego llamamos la función "close()":http://doc.qt.nokia.com/4.7/qiodevice.html#close que cierra el archivo para retornar la descripción del archivo al sistema operativo.
Ahora, vamos a pasar al slot save().
QString fileName = QFileDialog::getSaveFileName(this, tr("Guardar archivo"), "",
tr("Archivos de texto ('''.txt);;Archivos de C++ ('''.cpp '''.h)"));
if (fileName != "") {
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
// mensaje de error
} else {
QTextStream stream(&file);
stream << textEdit->toPlainText();
stream.flush();
file.close();
}
}
Cuando escribimos el contenido del editor de texto en el archivo, utillizamos la clase "QTextStream":http://doc.qt.nokia.com/4.7/qtextstream.html, que envuelve al objeto "QFile":http://doc.qt.nokia.com/4.7/qfile.html. El flujo de texto puede escribir QStrings directamente al archivo; "QFile":http://doc.qt.nokia.com/4.7/qfile.html sólo acepta los datos en bruto (char) con las funciones "write()":http://doc.qt.nokia.com/4.7/qiodevice.html#write de "QIODevice":http://doc.qt.nokia.com/4.7/qiodevice.html.