Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Programacion Con QT PDF
Programacion Con QT PDF
Hola, mi nombre es Martin Hernan Algañaraz, y debido a la falta de documentación referente a esta librería,
me decidí a escribir un pequeño tutorial, que espero les sea de utilidad.
Requisitos:
Obviamente la librería.
Serán necesarios conocimientos (al menos básicos de la STL), y programación orientada a
objetos.
Requisito indispensable, GANAS DE APRENDER.
Antes que nada, me gustaría aclarar, que si lo que están buscando es aprender a utilizar el QtDesigner, o el
KDevelop, dejenme decirles que se equivocaron de tuto, este tutorial, no va más alla de lo que dice el titulo,
DESARROLLO UTILIZANDO LA LIBRERIA QT 3.2. Por ese motivo, lo único que explicare es como utilizar la
librería en si, (los widgets, las señales, la herencia, los tipos etc...) algo, que considero necesario saber antes
de lanzarse sobre los poderosos IDES. Si lo que pretenden es aprender a programar en KDevelop o utilizar el
QTdesigner, les recomiendo leer el tutorial de Martin Sande, que para algo se quemo los dedos tecleando :).
Otra cosa, yo trato de explicar el uso "a mano" de esta librería, si bien en mi caso utilizo como editor el emacs
y una consola para compilar, no quiero decir que este demás utilizar los IDEs, puesto que para algo están, yo
personalmente prefiero hacerlo a mano, pero es solamente una cuestión de gustos (no me juzguen, soy
amante del Slackware).
Primero que nada, dare un ejemplo pequeño, sencillo y sin ninguna utilidad práctica, pero que para comenzar
estará bien:
Ej:
#include <qapplication.h>
#include <qpushbutton.h>
#include <qfont.h>
Primero que nada, quiero aclarar que el ejemplo dado, no es del todo básico, y pudo haber sido, mucho más
sencillo, pero debido a que la librería QT, esta íntimamente diseñada, para utilizarse con lenguajes orientados
a objetos, me pareció una buena manera de comenzar.
Lo primero que hago, es declarar tres ficheros de cabecera, que serán utilizados por la librería (notar que no
hace falta incluir el fichero iostream).
El fichero llamado qapplication.h, es la base de la librería, y con el cual la inicializamos, este fichero es
SIEMPRE NECESARIO.
El fichero llamado qpushbutton.h, es necesario, para la creación y utilización del widget boton.
El fichero llamado qfont.h, no fue necesario incluirlo en este ejemplo pero tampoco complica tanto las cosas,
este fichero, es el encargado de manejar las fuentes de los widgets que tengamos en la aplicación.
Bien, primero que nada me gustaría aclarar que en la librería QT, NO EXISTE el Formulario en si, (no hay
nada llamado QForm, o algo por el estilo), porque sencillamente somos nosotros los que tenemos que crear
los widgets, esto lo haremos todo el tiempo, especificando las propiedades y eventos que queremos que
nuestro widget reciba, y como los procese (gasearía: pulsación de un botón, cambio de tamaño del widget,
etc,etc..).
Como se ve en ejemplo anterior creamos una clase llamada CFormulario, que deriva directamente de otra
llamada QWidget, (la cual es la base de todos los widgets), y creamos un constructor con dos argumentos,
por defecto los cuales son QWidget *parent y const char *name. El primero es un puntero al widget que llamó
al objeto, (en este caso ninguno, por eso lo inicializamos a 0), y el segundo no es más que una cadena de
caracteres conteniendo el nombre, (también lo inicializamos siempre a 0). (Notar que en la implementación
del constructor, no es necesario inicializarlo).
2. Luego, lo inicializo pasándole como argumento el nombre del widget (en este caso botón), y el widget que
lo contendrá, (en este caso nuestro widget llamado CFormulario), por ultimo le asigno el texto que tendrá el
botón por defecto.
3. El tercer paso, por el momento lo saltaremos, como para no complicar las cosas, pero lo veremos más
adelante.
4. En el cuarto paso, sencillamente llamo a una función miembro llamada setFont de la clase QWidget, que
es la de cambiar la fuente (recordar, que la clase QWidget es la base de todos los widgets) , y le paso como
parámetros, el nombre de la fuente que tendrá, (puede ser cualquiera, "times,", "arial", "gotic" etc..), el
tamaño de la fuente, y por ultimo establezco la fuente en negrita. Para esto, no es necesario crear
previamente un objeto de la clase QFont, sino que llamo directamente al constructor y le paso los
parámetros.
5. En la función principal, la primera linea, que salta a la vista es QApplication Main ( argc , argv ), esta
función, es la encargada de inicializar la librería, y se le debe pasar los argumentos de main, para (en caso
que existan) procesar los argumentos de la linea de comando. No necesariamente debe llamarse Main,
podríamos haberle puesto programa, prueba, pepito, lo que se nos cante. Yo le suele llamar Main, por simple
preferencia.
6. Luego de inicializar la librería, lo que hago es crear una instancia de la clase que creamos previamente, y
le cambio el título con la función setCaption, de la clase QWidget.
8. Luego le digo a la librería, con la función setMainWidget de la clase QApplication, cual es el widget
principal, (el que tiene que actuar como formulario). y procesar según los eventos recibidos. Para esto, le
tengo que pasar como argumento la DIRECCIÓN DE MEMORIA del widget, (en este caso Form).
9. Y finalmente lo que hago con la función exec, es que la aplicacion se quede procesando los mensajes
recibidos, (los eventos), para luego poder manejarlos a nuestro antojo, es como un bucle de mensajes,
(bastante conocidos por los programadores de windows, y más especialmente los de visual c++).
Si bien la forma de trabajo de la librería, puede parecer un poco confusa en un primer momento, no debemos
olvidarnos, que la librería esta íntimamente asociada a la POO, y lo que nos puede parecer extraño en un
primer momento, pronto se torna tan natural, que sencillamente lo haces de reflejo.
Como dije en un primer momento de este tutorial, es indispensable saber programar con lenguajes orientados
a objetos (dígase c++, object pascal, java) preferentemente c++, que sera el lenguaje utilizado para este
tutorial.
Cualquier widget de la librería QT, es una clase, derivada de QWidget, y es por eso, que la mayoría de los
widgets tienen métodos y propiedades en común, como el ancho, y el alto (width, height) , el título
(setCaption) y la posición (pos) entre muchas otras. Además muchos widgets de la librería, pueden derivar de
otros, como por ejemplo el widget QComboBox, que esta formado por varios widgets (QListBox, QLineEdit,
QValidator etc..), esto, da una flexibilidad tremenda a la librería.
________________________________________________________________________________________
Tipos de datos:
________________________________________________________________________________________
Veamos ahora, la clase QString, que como se habrán dado cuenta no es más que una clase, de las QT, para
el tratamiento de las cadenas.
QString
Constructores:
QString ()
QString ( QChar ch )
QString ( const QString & s )
QString ( const QByteArray & ba )
QString ( const QChar * unicode, uint length )
QString ( const char * str )
QString ( const std::string & str )
Destructores:
~QString();
Normalmente, las clases de la librería QT, tienen sobrecargados el operador "=", y esta no es la excepción.
Tambien, mostraremos algunos miembros públicos, de la clase, muchos de ellos están sobrecargados
(overloading).
Esta función, retorna TRUE, si la cadena es NULA (NULL), o FALSE en caso contrario.
Esta función retorna TRUE, si la cadena esta vacía o FALSE en caso contrario
Esta función retorna un entero sin signo (uint o unsigned int), conteniendo la longitud de la cadena
Esta función rellena la cadena, con el carácter especificado, el numero de veces especificado ej:
QString cadena;
cadena.fill( 'H' , 10 ); //cadena = "HHHHHHHHHH"
Esta función es una de las más utilizadas, y agradecidas, (al menos por mi), sirve para combinar números,
con cadenas de caracteres ej:
QString str;
str = QString( "El decimal 63 es %1 en hexadecimal" ).arg( 63, 0, 16 );
// str == "El decimal 63 es 3f en hexadecimal"
Las siguientes funciones, hacen lo mismo, pero con distintos números o tipos, puesto que están
sobrecargadas.
Esta función, busca el carácter o la subcadena especificada dentro de la cadena, y retorna un entero, que
contiene la posición del carácter o la posición de la subcadena dentro de la cadena ej
Esta función retorna la posición de el carácter o cadena especificado, comenzando por el final ej:
QString cadena("Bananas");
int i = cadena.findRev( ' a ' ); // i = 5
Esta función, retorna el numero de veces, que el carácter o la subcadena especificada aparece dentro de la
cadena Ej:
QString section ( QChar sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const
QString section ( char sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const
QString section ( const char * sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const
QString section ( const QString & sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const
QString section ( const QRegExp & reg, int start, int end = 0xffffffff, int flags = SectionDefault ) const
Esta función retorna la subcadena, contenida dentro de la cadena a partir de la posición indicada
comenzando por la derecha Ej:
Esta función retorna una subcadena dentro de una cadena, a partir de la posición indicada comenzando por
la izquierda.
Esta función retorna la subcadena contenida dentro de la cadena, desde la posición 1 hasta la posición 2 Ej:
QString cadena ( "ejemplo de cadenas" );
QString cade = cadena.mid(11, cadena.length); //cade = cadenas
Esta función, retorna la cadena borra los espacios dentro de la cadena Ej:
Esta función, concatena una cadena o un carácter con otra cadena o carácter
Esta función, añade una cadena o carácter dentro de otra, comenzando por el principio de la cadena es
similar a poner insert (0,carácter)
Esta función, remueve x cantidad de caracteres dentro de una cadena , y retorna una referencia a un
QString , con los datos removidos Ej:
Esta función, remplaza los caracteres de la cadena, a partir de una posición dada ej:
QString & replace ( uint index, uint len, const QString & s )
QString & replace ( uint index, uint len, const QChar * s, uint slen )
QString & replace ( uint index, uint len, QChar c )
QString & replace ( uint index, uint len, char c )
QString & replace ( QChar c, const QString & after, bool cs = TRUE )
QString & replace ( char c, const QString & after, bool cs = TRUE )
QString & replace ( const QString & before, const QString & after, bool cs = TRUE )
QString & replace ( const QRegExp & rx, const QString & after )
QString & replace ( QChar c1, QChar c2 )
Estas funciones, son de conversión, pongo un ejemplo de un short, como para mostrar pero todas trabajan de
similar manera ej:
si la conversión, fue realizada con éxito, result retorna TRUE, en caso contrario retorna FALSE.
Operador sobrecargado +=
Estas funciones, retornan una referencia a un QString, a partir de otra cadena de tipo const char * Ej:
QString cade;
const char *cadena = "ejemplo de cadenas";
cade.setLatin1(cadena, strlen ( cadena ) );
Funciones relacionales:
Bueno, espero que con estas funciones puedan manipular las cadenas a gusto, lamentablemente no puse
todas las funciones, por una cuestión de salud (prevención contra la artritis deformante) , pero si las más
necesarias y utilizadas.
También, tenemos otra clase para el manejo de cadenas la clase QCString, lo único que difiere con la
anterior es que esta más orientada a las cadenas en C.
QCString:
Constructor por defecto
QCString ()
Constructor copia
QCString ( const QCString & s )
Constructor sobrecargado para contener datos del tipo const char *, y el tamaño máximo de la cadena
QCString ( const char * str, uint maxsize )
Función que dimensionaren la variable, para contener más caracteres dentro, y retorna TRUE si fue posible
bool resine ( uint len )
Función que retorna TRUE, si se pudo rellenar la variable con la letra especificada el numero de veces
especificado
bool fill ( char c, int len = -1 )
Función que retorna un QCString, con el formato de la cadena pasada como argumento.
QCString & sprintf ( const char * format, ... )
Función que retorna la posición de la letra buscada a trasves de una expresión regular
int find ( const QRegExp & rx, int index = 0 ) const
Función que retorna la posición de la letra pasada como argumento, la búsqueda comienza desde el final de
la cadena.
int findRev ( char c, int index = -1, bool cs = TRUE ) const
int findRev ( const char * str, int index = -1, bool cs = TRUE ) const
int findRev ( const QRegExp & rx, int index = -1 ) const
Función que retorna el numero de veces, que el carácter fue encontrado en la cadena.
int contains ( char c, bool cs = TRUE ) const
int contains ( const char * str, bool cs = TRUE ) const
int contains ( const QRegExp & rx ) const
Función que inserta una cadena dentro de otra, a partir de la posición pasada como argumento.
QCString & insert ( uint index, const char * s )
QCString & insert ( uint index, char c )
Función que agrega una cadena dentro de otra comenzando desde el principio
QCString & prepend ( const char * s )
Función que convierte la cadena a un short (entero corto) y retorna la cadena convertida
short toShort ( bool * ok = 0 ) const
Función que convierte la cadena a un ushort (entero corto sin signo) y retorna la cadena convertida
ushort toUShort ( bool * ok = 0 ) const
Función que convierte la cadena a un uint (entero sin signo) y retorna la cadena convertida
uint toUInt ( bool * ok = 0 ) const
Función que convierte la cadena a un long (entero largo) y retorna la cadena convertida
long toLong ( bool * ok = 0 ) const
Función que convierte la cadena a un ulong (entero largo sin signo) y retorna la cadena convertida
ulong toULong ( bool * ok = 0 ) const
Función que convierte la cadena a un double (doble presidencia) y retorna la cadena convertida
double toDouble ( bool * ok = 0 ) const
Función que cambia el contenido de la cadena, por otro pasado como argumento
QCString & setStr ( const char * str )
Función que cambia la posición del carácter pasado como argumento y expande la cadena si es necesario.
bool setExpand ( uint index, char c )
Operadores sobrecargados
QDataStream & operator<< ( QDataStream & s, const QCString & str )
QDataStream & operator>> ( QDataStream & s, QCString & str )
bool operator== ( const QCString & s1, const QCString & s2 )
bool operator== ( const QCString & s1, const char * s2 )
bool operator== ( const char * s1, const QCString & s2 )
bool operator!= ( const QCString & s1, const QCString & s2 )
bool operator!= ( const QCString & s1, const char * s2 )
bool operator!= ( const char * s1, const QCString & s2 )
bool operator< ( const QCString & s1, const char * s2 )
bool operator< ( const char * s1, const QCString & s2 )
bool operator<= ( const QCString & s1, const char * s2 )
bool operator<= ( const char * s1, const QCString & s2 )
bool operator> ( const QCString & s1, const char * s2 )
bool operator> ( const char * s1, const QCString & s2 )
bool operator>= ( const QCString & s1, const char * s2 )
bool operator>= ( const char * s1, const QCString & s2 )
QCString & operator+= ( const char * str )
QCString & operator+= ( char c )
const QCString operator+ ( const QCString & s1, const QCString & s2 )
const QCString operator+ ( const QCString & s1, const char * s2 )
const QCString operator+ ( const char * s1, const QCString & s2 )
const QCString operator+ ( const QCString & s, char c )
const QCString operator+ ( char c, const QCString & s )
Veremos ahora, el tipo QByteArray, que no es más que un array de bytes, como su nombre lo indica.
QByteArray
Constructor por defecto
QByteArray ()
Continuamos con la clase QPtrCollection, que define varias función para las listas
QPrtCollection
Función, que retorna TRUE, si la opción deletrearos esta activa
bool papeleteemos () const
Constructor copia
QPtrCollection ( const QPtrCollection & source )
Destructor
virtual ~QPtrCollection ()
Función que crea una copia del ítem, y lo inserta dentro de la clase
virtual ítem newItem ( ítem d )
Seguiremos ahora, con la clase QPtrList, que no es más que una lista de la STL, pero mejorada
QPtrList
Constructor por defecto
QPtrList ()
Destructor
~QPtrList ()
Operadores sobrecargados
QPtrList<type> & operator= ( const QPtrList<type> & list )
bool operator== ( const QPtrList<type> & list ) const
bool operator!= ( const QPtrList<type> & list ) const
Función que remueve un ítem de la lista, por su índice, si el ítem fue borrado, retorna TRUE
bool remove ( uint index )
Función que remueve el ítem actual de la lista, y retorna TRUE si el ítem fue borrado
bool remove ()
Función que ordena la lista, utilizando el método de ordenación QSort (este es de los 70 )
void sort ()
Veamos ahora, el widget QTextStream, que sirve para crear stream de texto
QTextStream
Enumeración con el modo de encode que tendrá el stream
enum Encoding { Locale, Latin1, Unicode, UnicodeNetworkOrder, UnicodeReverse, RawUnicode,
UnicodeUTF8 }
Constructor por que asocia el stream a un QIODevice (dispositivo de entrada ¿lindo no?)
QTextStream ( QIODevice * iod )
Constructor por que asocia el stream a QString y se le puede especificar el tipo de acceso (enumeración de
la clase QFile)
QTextStream ( QString * str, int filemode )
Constructor por que asocia el stream a una estructura FILE * de c (no recomendado)
QTextStream ( FILE * fh, int mode )
Destructor
virtual ~QTextStream ()
Función que lee una cantidad especifica de bytes de un stream, y retorna una referencia a otro stream
QTextStream & readRawBytes ( char * s, uint len )
Función que escribe una cantidad especifica de bytes de un stream, y retorna una referencia a otro stream
QTextStream & writeRawBytes ( const char * s, uint len )
Seguiremos con la clase QPoint, que es una de las encargadas de manejar puntos y coordenadas.
QPoint:
Constructor por defecto
QPoint ()
Operadores sobrecargados
QPoint & operator+= ( const QPoint & p )
QPoint & operator-= ( const QPoint & p )
QPoint & operator*= ( int c )
QPoint & operator*= ( double c )
QPoint & operator/= ( int c )
QPoint & operator/= ( double c )
bool operator== ( const QPoint & p1, const QPoint & p2 )
bool operator!= ( const QPoint & p1, const QPoint & p2 )
const QPoint operator+ ( const QPoint & p1, const QPoint & p2 )
const QPoint operator- ( const QPoint & p1, const QPoint & p2 )
const QPoint operator* ( const QPoint & p, int c )
const QPoint operator* ( int c, const QPoint & p )
const QPoint operator* ( const QPoint & p, double c )
const QPoint operator* ( double c, const QPoint & p )
const QPoint operator- ( const QPoint & p )
const QPoint operator/ ( const QPoint & p, int c )
const QPoint operator/ ( const QPoint & p, double c )
QDataStream & operator<< ( QDataStream & s, const QPoint & p )
QDataStream & operator>> ( QDataStream & s, QPoint & p )
Función que retorna el ancho y alto máximo del QSize pasado como argumento
QSize expandedTo ( const QSize & otherSize ) const
Función que retorna el ancho y alto mínimo del QSize pasado como argumento
QSize boundedTo ( const QSize & otherSize ) const
Operadores sobrecargados
QSize & operator+= ( const QSize & s )
QSize & operator-= ( const QSize & s )
QSize & operator*= ( int c )
QSize & operator*= ( double c )
QSize & operator/= ( int c )
QSize & operator/= ( double c )
Ahora mostraremos la clase QValidator, que sirve para validar datos dentro de los widgets.
QValidator
Constructor por defecto
QValidator ( QObject * parent, const char * name = 0 )
Destructor
~QValidator ()
Esta función valida los datos y retorna Invalid si la entrada es incorrecta o Acceptable si es correcta.
virtual State validate ( QString & input, int & pos ) const = 0
Esta función establece el tipo de validación que queremos darle a los datos.
virtual void fixup ( QString & input ) const
Veremos a continuación la clase QStrList, que sirve para el manejo de arrays de cadenas de tipo char **
QStrList
Constructor por defecto
QStrList ( bool deepCopies = TRUE )
Constructor copia
QStrList ( const QStrList & list )
Destructor
~QStrList ()
operador sobrecargado
QStrList & operator= ( const QStrList & list )
QMemArray
Función que crea un Iterador.
typedef type * Iterator
Operador sobrecargado
QMemArray<type> & operator= ( const QMemArray<type> & a )
Función que retorna una referencia a la cantidad de datos que contiene el array.
uint nrefs () const
Función que redimensiona el array, pasándole el tipo de optimización requerido, la optimización puede ser
QGArray::MemOptim (optimiza la memoria) QGArray::SpeedOptim (optimiza la velocidad).
bool resine ( uint size, Optimization optim )
Función que (si el array esta ordenado) realiza una búsqueda binaria de V en el array.
int bsearch ( const type & v ) const
Operador sobrecargado
type & operator[] ( int index ) const
Operadores sobrecargados
operator const type * () const
bool operator== ( const QMemArray<type> & a ) const
bool operator!= ( const QMemArray<type> & a ) const
Función que retorna un puntero al Iterador del array, con el primer dato del array.
Iterator begin ()
Función que retorna un puntero al Iterador del array, con el ultimo dato del array.
Iterator end ()
Función que retorna un puntero al Iterador constante del array, con el primer dato del array.
ConstIterator begin () const
Función que retorna un puntero al Iterador constante del array, con el ultimo dato del array.
ConstIterator end () const
Si bien esto de mostrar unos cuantos tipos de datos y clases de entrada, puede parecer algo pesado, no lo
hago a propósito ni tampoco es necesario que se los conozcan al pie de la letra, solamente los pongo aquí, a
modo de referencia. Noten que puse estos datos ANTES de comenzar a "tirar código", ya que sino no sabrían
que es cada cosa, ni para que sirve, ni mucho menos como trabaja.
Pondre ahora, las enumeraciones que contiene la clase QT, no es interesante leerlo, pero si tenerlo como
referencia, puesto que las usaremos bastante.
QT Enumeraciònes
Enumeración, que contiene las medidas de pintado (pixeles, twips mitric etc...)
enum PaintUnit { PixelUnit, LoMetricUnit, HiMetricUnit, LoEnglishUnit, HiEnglishUnit, TwipsUnit }
Enumeración, que contiene el tipo de plataforma windows que usamos. (que triste)
enum WindowsVersion { WV_32s = 0x0001, WV_95 = 0x0002, WV_98 = 0x0003, WV_Me = 0x0004,
WV_DOS_based = 0x000f, WV_NT = 0x0010, WV_2000 = 0x0020, WV_XP = 0x0030, WV_NT_based =
0x00f0 }
para usar estas enumeraciones y tipos, tenemos que hacerlo de esta manera ej:
QLabel *label =
new QLabel (...);
label-
>setTextFormat (Qt::PlainText);
________________________________________________
QWidget:
Miembros públicos:
Destructor.
~QWidget ()
Función que retorna el estilo de GUI, (Motif, Motif plus, Marmol, Plastic etc..)
QStyle & style () const
Función que cambia el estilo de GUI, (Motif, Motif plus, Marmol, Plastic etc..)
void setStyle ( QStyle * style )
Función que cambia el estilo de GUI, (Motif, Motif plus, Marmol, Plastic etc..) y retorna un puntero con el
nuevo estilo
QStyle * setStyle ( const QString & style )
Función que retorna TRUE, si el widget esta abilitado, y el widget antecesor, esta abilitado también
bool isEnabledTo ( QWidget * ancestor ) const
Función que retorna la geometría relativa del widget, incluyendo el frame de la ventana
QRect frameGeometry () const
Función que retorna la geometría relativa del widget, excluyendo el frame de la ventana.
const QRect & geometry () const
Función que retorna la coordenada x (horizontal) del widget dentro del widget antecesor ,incluyendo el frame
de la ventana
int x () const
Función que retorna la coordenada y (vertical) del widget dentro del widget antecesor ,incluyendo el frame de
la ventana
int y () const
Función que retorna un QPoint, conteniendo las coordenadas de la posición del widget
QPoint pos () const
Función que retorna un QSize, conteniendo el tamaño del widget, incluyendo el frame
QSize frameSize () const
Función que retorna un QSize, conteniendo el tamaño del widget, excluyendo el frame
QSize size () const
Función que retorna un QRect con la geometría interna del widget, excluyendo el frame
QRect rect () const
Función que establece el incremento del widget (lo agranda), a trabes de un QSize
void setSizeIncrement ( const QSize & )
Función que retorna un BackgroundMode, conteniendo el color del fondo del widget.
BackgroundMode backgroundMode () const
Función que retorna un Qpalette, con la paleta de colores usada por el widget
const QPalette & palette () const
Función que retorna un QBrush, conteniendo la brocha usada para dibujar el widget
const QBrush & backgroundBrush () const
Función que retorna un QFont, conteniendo el estilo de fuente usada por el widget.
QFont font () const
Función que retorna TRUE, si el MouseTracking esta abilitado para el widget, si no retorna FALSE.
bool hasMouseTracking () const
Función que causa que solamente los pixeles del widget del ancho del bitmap que correspondan a un bit
sean visibles
Función que causa que solamente los pixeles del widget del ancho de la región que correspondan a un bit
sean visibles
virtual void setMask ( const QRegion & región )
Función que retorna un QWidget, conteniendo el widget que tiene el foco actualmente.
QWidget * focusProxy () const
Slots públicos:
Función, que establece si los eventos de entrada del widget estarán deshabilitados o no
void setDisabled ( bool disable )
Función, borra y dibuja el un área del widget si erase es true, no borra el widget
void repaint ( int x, int y, int w, int h, bool erase = TRUE )
void repaint ( const QRect & r, bool erase = TRUE )
void repaint ( const QRegion & reg, bool erase = TRUE )
Estos, no son todas las funciones miembro y slots públicos, que contiene esta clase, pero si las más usadas
o necesitadas, no pude ponerlas todas, sencillamente porque no me dan los dedos para teclear tanto.
Como vemos, no es algo complicado, mostrare un ejemplo como para simplificar un poco las cosas:
ej:
Fichero cabecera.h:
#ifndef CABECERA_H
#define CABECERA_H
#include <qvbox.h>
#include <qstringlist.h>
class QPushButton; //esto es para no tener que poner aqui el archivo de cabecera del widget, (una mentirilla
piadosa para el enlazador)
class QLineEdit;
class CPrincipal : public QVBox //clase derivada de QVBox (para ordenar los widgets dentro de la aplicacion)
{
Q_OBJECT
public:
CPrincipal (QWidget *parent = 0, const char *name = 0); //constructor
#endif
Fichero cabecera.cpp:
#include "cabecera.h"
#include <qlabel.h>
#include <qmessagebox.h>
#include <qpushbutton.h>
#include <qlineedit.h>
/***************************************************************************************/
CPrincipal::CPrincipal(QWidget *parent, const char *name) //Constructor, aqui es donde se crean e inicializan
los widgets que tendrá la aplicacion
: QVBox(parent,name)
{
/***************************************************************************************/
/*Creo los widgets*/
/***************************************************************************************/
/***************************************************************************************/
/*Les asigno las propiedades que tendrán*/
/***************************************************************************************/
/***************************************************************************************/
/*Conecto las señales a las que deberán responder*/
/***************************************************************************************/
/***************************************************************************************/
/*Estas funciones, son los llamados SLOTS, que definimos para responder a las señales que los widgets
emiten.*/
/***************************************************************************************/
void CPrincipal::GetNombre()
{
for ( QStringList::Iterator it = lstNombres->begin(); it != lstNombres->end(); ++it )
{
QMessageBox::information(this, "Ejemplo 1", *it);
}
}
void CPrincipal::AlmacenarNombre()
{
lstNombres->append(txt_nombre->text() );
txt_nombre->clear();
}
Fichero main.cpp:
#include <qapplication.h> //Si o Si tiene que estar, porque es el esqueleto de toda la aplicacion
#include "cabecera.h"
int main (int argc , char **argv )
{
QApplication Main(argc, argv); //Inicializo la librería
CPrincipal Form; //creo una instancia de la clase CPrincipal
Form.setCaption("Ejemplo 1"); //sencillamente le cambio el texto al formulario
Form.show(); //lo muestro
/*
le digo a la aplicacion que este sera el widget principal, y que aquí se deberán procesar todos los eventos
*/
Main.setMainWidget(&Form); /
return Main.exec(); //el famosisimo bucle de mensajes (Morite de envidia MSVC++)
}
Espero que no les resulte muy complicado de entender (cosa que no creo), pasemos a explicarlo un poco.
en el, definimos dos ficheros de cabecera, los cuales son qvbox.h y qstringlist.h
1): el primero es un widget especial, que nos provee la librería QT, para ordenar de una manera vertical los
widgets de la aplicacion, y el segundo es un widget invisible, ( solamente para uso interno ) que sirve para
crear un array de objetos QString ( widget para las cadenas ). Los métodos y propiedades, ya los explicare a
su tiempo.
2): luego, se ve claramente que creamos dos clases distintas una llamada QPushButton, y otra llamada
QLineEdit, estas clases, no son realmente necesarias, se hace para que el compilador encuentre ese tipo de
dato, y no de error en tiempo de compilación, los ficheros de cabecera de esos widgets, serán implementados
luego en al fichero cabecera.cpp, que es realmente donde se necesitan.
3): Aquí, creamos la clase CPrincipal, que sera la que usaremos a lo largo del programa, esta deriva como
vemos de una clase de la librería QT, que como ya dijimos sirve para alinear los widgets verticalmente.
4): La linea Q_OBJECT, sirve para que la librería QT, identifique la clase, y permita crear "secciones
especiales" para definir funciones de respuesta o crearnos nuestras propias señales, como veremos más
adelante.
5): Como la clase CPrincipal es derivada de la clase QVBox, y esta a su ves de la clase QWidget, deberemos
CASI SIEMPRE crear un constructor de esta manera. El parámetro QWidget *parent = 0, sirve para saber de
donde se deriva la clase, y el parámetro const char *name = 0, es el nombre, que por defecto es 0 (o sea
NULL). Esto es útil, para cuando creamos varias instancias de la clase, y la mayoría de los constructores de
los widgets suelen estar definidos de esta manera, pondré un ejemplo.
como vemos, this es la clase sobre la cual descansara el widget, y nombre es el nombre de la instancia que
le hemos dado, en realidad this representa otra cosa, pero asumo que eso ya lo saben.
6): La seccion public slots: sirve para poder definir funciones de respuesta para las señales que emitirán los
widgets que tengamos, los parámetros que podemos pasarles a estas funciones TIENEN QUE COINCIDIR
EXACTAMENTE CON LOS PARAMETROS DE LA SEÑAL A LA QUE ATENDERAN. Esto es un requisito
indispensable para que las señales sean atendidas correctamente, si no se cumple este requisito la
aplicacion no funcionara correctamente. Las señales de los distintos widgets, las mostrare más adelante.
7): Luego simplemente creo instancias de los widgets que tendrá la aplicación, notar que no es necesario
definir todos los widgets, sino solamente aquellos a los que llamaremos desde las distintas funciones de
respuesta o funciones internas de la clase (osea aquellos que compartiremos entre las distintas funciones).
1): Lo primero que hacemos aqui, es incluir los ficheros de cabecera necesarios para poder utilizar los
distintos widgets de la aplicacion.
2): Luego creamos el constructor que es derivado (en este caso) de la clase QVBox.
3): Lo siguiente que hacemos sera reservar memoria para los widgets e inicializarlos.
4): Acto seguido, les asigno las distintas propiedades que tendrán, en este caso el texto del label y los
botones, notar que el nombre de la propiedad es igual para todos los widget mostrados, pero esta propiedad
es interna de cada widget y no es heredada a traves de la clase QWidget de la cual derivan todos los widgets.
5): Luego conecto las señales que me interesan a las funciones de respuesta que implementaremos más
adelante, los parámetros de la función connect son los siguientes:
connect ( "nombre del widget que queremos conectar", SIGNAL( "el nombre de la señal que queremos
atender" ), "el widget que posee la función de respuesta para esta señal" , SLOT ( "la función de respuesta en
si (definida por nosotros o no)" ) );
la función de respuesta no tiene que ser si o si una función de respuesta, sino que también puede ser una
señal que hayamos implementado o alguna señal interna de algún widget. Mostrare un ejemplo:
también podemos definir varias funciones de respuesta para una misma señal, las cuales serán procesadas
en el orden en el que fueron definidas.
6): Ahora solamente creamos las funciones de respuesta como si fueran funciones miembro normales de la
clase, no hay nada especial en esto. Las propiedades y funciones que intervienen en este caso serán
explicadas a lo largo del tutorial (sean pacientes).
Ya explicado la parte más difícil, solo nos resta explicar el fichero main.cpp
1): Lo primero que hacemos es incluir el fichero de cabecera qapplication.h, que es necesario para poder
utilizar la librería, y luego incluimos nuestro fichero de cabecera llamado cabecera.h, en el cual tenemos ya
nuestro widget preparado.
2): La función QApplication, sirve para inicializar la librería, y sin esta no podremos ejecutar el programa.
3): luego creamos una instancia de nuestro widget, definimos el nombre que se vera en la barra de titulo (esta
linea no es necesaria) y lo mostramos .
4): Aquí lo que se hace es "vincular" nuestro widget con la aplicacion y de ese modo, ponerlo como widget
principal, el cual sera el primero que veamos cuando iniciemos la aplicacion.
5): Luego, en en retorno llamo a la función exec de la clase QApplication, para que se encargue de procesar
todos los eventos (señales) que serán emitidos por la aplicacion. (reitero morite de envidia MSVC++).
Para compilar tenemos que abrir una consola e ir dentro del directorio donde están los ficheros de la
aplicacion que queramos crear y tipear qmake -project, esto hace que se cree un fichero de proyecto, el
nombre que tendrá la aplicación sera el mismo que el nombre del directorio, luego tipeamos qmake a secas
para que se cree el fichero Makefile automáticamente, y finalmente typeamos make para compilar.
Espero que no les haya quedado ninguna duda, (sacando la de las propiedades y eventos), pero si no
entendieron algo o simplemente desean preguntar algo relacionado con el tuto, no duden en escribirme a
martin_alganaraz@yahoo.com.ar
Veamos ahora, las propiedades y eventos de los widgets que hemos usado en esta aplicacion,
comenzaremos con el widget más popular o más usado el QPushButton.
El widget QPushButton, es el tipico boton que existe en todas las aplicaciones (al menos las que yo conozco)
QPushButton:
Destructor
~QPushButton ()
Función para crear un boton toogle (se queda presionado si le hacemos click() ).
void setToggleButton ( bool )
Función que cambia la propiedad AutoDefault del boton haciendo que no sea un boton automático por
defecto.
Función que cambia el estado del boton haciendo que este sea o no por defecto.
virtual void setDefault ( bool def )
Función que inserta un menú del tipo pop-up (desplegable) en el boton.
void setPopup ( QPopupMenu * popup )
Función que hace que el boton sea un boton flotante (sin borde).
void setFlat ( bool )
Función que retorna una tecla aceleradora (ejemplo Alt+x) asociada al boton.
QKeySequence accel () const
Señal que es emitida cuando se suelta el puntero del mouse dentro de los limites del boton.
void released ()
Señal que es emitida cuando el boton cambia de estado, si TRUE es pasado como argumento el boton estará
toogled o FALSE en caso contrario.
void toggled ( bool on )
Continuamos con el Widget QLineEdit, el cual es el tipico cuadro de texto, que también se suele encontrar en
la mayoría de las aplicaciones.
QLineEdit:
Constructor por defecto
QLineEdit ( QWidget * parent, const char * name = 0 )
Destructor
~QLineEdit ()
Función que retorna la posición del cursor dentro del QLineEdit. cursor de texto, no mouse :)
int cursorPosition () const
Función que mueve el cursor la cantidad de caracteres contenida en steps, si mark es TRUE, selecciona los
caracteres que estén detrás del cursor
void cursorForward ( bool mark, int steps = 1 )
Función que mueve el cursor la cantidad de caracteres contenida en steps, si mark es TRUE, selecciona los
caracteres que estén delante del cursor
void cursorBackward ( bool mark, int steps = 1 )
Función que hace que si el texto no esta seleccionado borra el carácter que esta a la derecha del cursor, y
mueve el siguiente carácter un carácter más atrás (es el backspace del teclado)
void backspace ()
Función que actúa como la tecla home del teclado, si mark es TRUE, selecciona el texto.
void home ( bool mark )
Función que actúa como la tecla fin o end del teclado, si mark es TRUE, selecciona el texto.
void end ( bool mark )
Función que retorna TRUE si el texto contenido en el QLineEdit fue modificado por el usuario.
bool isModified () const
Función que retorna TRUE si esta permitido usar la función undo del QLineEdit.
bool isUndoAvailable () const
SLOTS PUBLICOS:
Función que aplica la función undo (desacer) dentro del QLIneEdit (morite de envidia MSVC++)
virtual void undo ()
Función que aplica la función redo (rehacer) dentro del QLIneEdit (morite de envidia MSVC++)
virtual void redo ()
Función que establece si los caracteres contenidos dentro del QLineEdit serán visibles o no (Que tipo de
mascara usara: Normal || NoEcho (oculta los caracteres) || Password (oculta los caracteres tras asteriscos)
virtual void setEchoMode ( EchoMode )
Función que cambia la alineación dentro del QLineEdit, los posibles valores son: Qt::AlignAuto, Qt::AlignLeft,
Qt::AlignRight, Qt::AlignHCenter.
virtual void setAlignment ( int flag )
Señales:
Señal emitida cuando la seleccion del texto dentro del QLineEdit cambia.
void selectionChanged ()
Continuemos ahora, con el widget QMessageBox, que es el tipico cuadro de dialogo de toda aplicación.
QMessageBox:
Enumeracion que contiene el tipo de icono que tendrá el cuadro de dialogo
enum Icon { NoIcon = 0, Information = 1, Warning = 2, Critical = 3, Question = 4 }
Constructor con el titulo, el texto, el icono, la cantidad de botones que tendrá, si es modal o no, y el borde.
QMessageBox ( const QString & caption, const QString & text, Icon icon, int button0, int button1, int button2,
QWidget * parent = 0, const char * name = 0, bool modal = TRUE, WFlags f = WStyle_DialogBorder )
Destructor
~QMessageBox ()
Función que retorna el formato del texto contenido dentro del QMessageBox.
TextFormat textFormat () const
Función que cambia el formato del texto contenido dentro del QMessageBox.
void setTextFormat ( TextFormat )
int information ( QWidget * parent, const QString & caption, const QString & text, int button0, int button1 = 0,
int button2 = 0 )
int information ( QWidget * parent, const QString & caption, const QString & text, const QString & button0Text
= QString::null, const QString & button1Text = QString::null, const QString & button2Text = QString::null,
int defaultButtonNumber = 0, int escapeButtonNumber = -1 )
int question ( QWidget * parent, const QString & caption, const QString & text, int button0, int button1 = 0,
int button2 = 0 )
int question ( QWidget * parent, const QString & caption, const QString & text, const QString & button0Text =
QString::null, const QString & button1Text = QString::null, const QString & button2Text = QString::null,
int defaultButtonNumber = 0, int escapeButtonNumber = -1 )
int warning ( QWidget * parent, const QString & caption, const QString & text, int button0, int button1,
int button2 = 0 )
int warning ( QWidget * parent, const QString & caption, const QString & text, const QString & button0Text =
QString::null, const QString & button1Text = QString::null, const QString & button2Text = QString::null,
int defaultButtonNumber = 0, int escapeButtonNumber = -1 )
int critical ( QWidget * parent, const QString & caption, const QString & text, int button0, int button1,
int button2 = 0 )
int critical ( QWidget * parent, const QString & caption, const QString & text, const QString & button0Text =
QString::null, const QString & button1Text = QString::null, const QString & button2Text = QString::null,
int defaultButtonNumber = 0, int escapeButtonNumber = -1 )
void about ( QWidget * parent, const QString & caption, const QString & text )
Ejemplo de uso:
switch ( mb.exec() )
{
case QMessageBox::Yes:
//acciones
break;
case QMessageBox::No:
//acciones
break;
case QMessageBox::Cancel:
//acciones
break;
}
Y llegamos al ultimo widget usado en nuestra aplicacion, aunque no es un widget en realidad, (el objeto
QStringList es un tipo de dato propio de la librería QT).
QStringList:
Constructor por defecto
QStringList ()
Constructor copia
QStringList ( const QStringList & l )
Función que busca y cambia una cadena o carácter en la lista reemplazándolo por otro pasado como
argumento.
QStringList & gres ( const QString & before, const QString & after, bool cs = TRUE )
Función que busca y cambia una cadena o carácter en la lista que coincida con una expresión regular
remplazándolo por otro pasado como argumento.
QStringList & gres ( const QRegExp & rx, const QString & after )
Función que convierte una lista de caracteres ascii (QStrList) a una QStringList (unicode)
QStringList fromStrList ( const QStrList & ascii )
Bueno, parece que terminamos con las propiedades y los métodos, aunque faltan algunos, (que no los pude
incluir por falta de tiempo), la gran mayoría y los más utilizados se encuentran traducidos. Mostrare el resto
de los widgets más adelante.
Veamos un ejemplo más, un poquito más avanzado, y veremos otro widget bastante útil el QTable, para
estudiarlo después.
Ejemplo 2:
Fichero cabecera.h
#ifndef CABECERA_H
#define CABECERA_H
#include <qvbox.h>
#include <qstringlist.h>
class QPushButton;
class QLineEdit;
class QTable;
public slots: //funciones de respuesta a las señales que emiten los widgets
void GetNombre();
void AlmacenarNombre();
private:
QStringList *lstNombres; //los widget que tendrá la aplicacion
QPushButton *cmd_nombre;
QLineEdit *txt_nombre;
QTable *rejilla;
};
#endif
Fichero cabecera.cpp:
#include "cabecera.h"
#include <qlabel.h>
#include <qmessagebox.h>
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qtable.h>
#include <qheader.h>
/**************************************************************************/
/*Creo los widgets de la aplicacion*/
/**************************************************************************/
txt_nombre = new QLineEdit(this, "txt_nombre");
cmd_nombre = new QPushButton (this, "cmd_nombre");
QPushButton *cmd_mostrar = new QPushButton (this, "cmd_mostrar");
QPushButton *cmd_salir = new QPushButton(this, "cmd_salir");
rejilla = new QTable(this,"rejilla");
QHeader *cabecera = rejilla->horizontalHeader();
/**************************************************************************/
/**************************************************************************/
/* Los preparo*/
/**************************************************************************/
cmd_salir->setText("Terminar Aplicacion");
cmd_mostrar->setText("Mostrar nombres almacenados");
cmd_nombre->setText("Almacenar nombre");
rejilla->setNumCols(1);
rejilla->setNumRows(0);
cabecera->setLabel(0,"Nombres almacenados",180);
cabecera->setResizeEnabled(FALSE,0);
this->setMinimumSize(500,500);
this->setMaximumSize(1000,1000);
/**************************************************************************/
/**************************************************************************/
/*conecto sus señales */
/**************************************************************************/
connect (cmd_nombre, SIGNAL (clicked () ), this, SLOT (AlmacenarNombre () ) );
connect (txt_nombre, SIGNAL (returnPressed()), this, SLOT (AlmacenarNombre() ) );
connect (cmd_mostrar, SIGNAL (clicked() ), this, SLOT (GetNombre()) );
connect (cmd_salir, SIGNAL (clicked() ), this, SLOT (close() ) );
/**************************************************************************/
}
void CPrincipal::GetNombre()
{
int i = 0;
}
}
void CPrincipal::AlmacenarNombre()
{
lstNombres->append(txt_nombre->text() );
txt_nombre->clear();
}
Fichero main.cpp:
#include "cabecera.h"
#include <qapplication.h>
Como verán se trata del primer ejemplo de este tutorial, pero levemente modificado (tuneado como dirían en
mi barrio).
1): En el fichero de cabecera (cabecera.h) agregamos una definición de la clase QTable (para engañar al
enlazador) y definimos un nuevo objeto llamado rejilla, del tipo QTable. Hasta aqui nada nuevo.
2): El segundo fichero que analizaremos sera cabecera.cpp.
Primero, incluimos 2 ficheros de cabecera, llamados qtable.h, que contiene la definición de la clase QTable y
el otro llamado qheader.h, que contiene la definición de la clase QHeader necesaria para poder manejar las
celdas que sean fixed, o sea las que contienen un titulo y sirven para mostrar información sobre una
determinada columna o fila.
Después de unas lineas, vemos que al objeto rejilla y cabecera les asignamos algunas propiedades.
Una ves visto el constructor, pasemos a ver la función de respuesta GetNombre() definida por nosotros.
1): La función mimbro setItem, de la tabla lo que hace (como se habrán dado cuenta) es asignar un nuevo
ítem a la tabla en la fila y columna especificadas.
2): Como vemos el fichero de cabecera de QTableItem no aparece por ningún lado, y esto es así porque este
widget, esta incluido en el fichero de cabecera qtable.h, ya que se trata de un widget especial de la clase
QTable, el cual se encarga de asignar nuevos items a la tabla. Sus parámetros son los siguientes:
El parámetro rejilla (como se habrán dado cuenta) es el widget al que hará referencia (sobre el cual va a
trabajar).
El parámetro QTableItem::Never lo que hace es decirle a la tabla, que los items no podrán ser modificados,
también podríamos haber seleccionado QTableItem::Always, que es para que los ítem de la tabla puedan ser
modificados a gusto, o QTableItem::WhenCurrent, que sirve para que los items puedan ser modificados,
solamente si el foco del teclado esta sobre ellos, y el ultimo es QTableItem::OnTyping, que sirve para que el
ítem pueda ser modificado solamente si se hace doble-click sobre el.
El resto del código, no lo explicare, porque creo que no merece la pena, solo basta con decir que los
iteradores no son algo exclusivo de la librería QT, sino que es algo propio de la STL, la cual es un requisito
comprender para leer y entender este tuto.
QTable:
Constructor por defecto
QTable ( QWidget * parent = 0, const char * name = 0 )
Destructor
~QTable ()
Función que retorna una enumeración con el tipo de seleccion usado actualmente
SelectionMode selectionMode () const
Función que retorna un QRect con la geometría de una celda, en la fila y la columna especificada
virtual QRect cellGeometry ( int row, int col ) const
Función que retorna un entero con la coordenada X de la columna pasada como argumento
virtual int columnPos ( int col ) const
Función que retorna un entero con la coordenada Y de la columna pasada como argumento
virtual int rowPos ( int row ) const
Función que retorna un entero, con el numero de fila donde estamos actualmente posicionados
int currentRow () const
Función que retorna un entero, con el numero de columna donde estamos actualmente posicionados
int currentColumn () const
Función que retorna TRUE si la fila y la columna pasadas como argumento se encuentran actualmente
seleccionadas.
bool isSelected ( int row, int col ) const
Función que retorna TRUE, si la rejilla (las celdas) están visibles o FALSE en caso contrario
bool showGrid () const
Función que retorna TRUE, si las columnas pueden ser movidas por el usuario.
bool columnMovingEnabled () const
Función que retorna TRUE, si las filas pueden ser movidas por el usuario.
bool rowMovingEnabled () const
Función que retorna TRUE, si cuando se le hace click en la cabecera de la columna, se selecciona toda la
columna, si no retorna FALSE.
bool sorting () const
Función que sirve para mover un ítem, (sin borrarlo) indicado por el parámetro QTableItem de un lugar a otro,
puede ser a otra celda o a otra tabla.
virtual void takeItem ( QTableItem * i )
Función que agrega un QWIDGET (o sea cualquier widget!!!!) dentro de una celda en la tabla. jeje
virtual void setCellWidget ( int row, int col, QWidget * e )
Función que retorna un QRect, con el tamaño de la celda pasada como argumento.
virtual QRect cellRect ( int row, int col ) const
Esta función, y como pintar lo explicare un un segundo tutorial, puesto que el Canvas de QT es más que
complejo.
virtual void paintCell ( QPainter * p, int row, int col, const QRect & cr, bool selected )
Esta función, y como pintar lo explicare un un segundo tutorial, puesto que el Canvas de QT es más que
complejo.
virtual void paintCell ( QPainter * p, int row, int col, const QRect & cr, bool selected,
Esta función, y como pintar lo explicare un un segundo tutorial, puesto que el Canvas de QT es más que
complejo.
const QColorGroup & cg )
Esta función, y como pintar lo explicare un un segundo tutorial, puesto que el Canvas de QT es más que
complejo.
virtual void paintFocus ( QPainter * p, const QRect & cr )
Función que actualiza los encabezados de la tabla, y los sincroniza con la seleccion actual.
void updateHeaderStates ()
Slots:
Función que establece si rejilla (las filas y las columnas) serán visibles o no
virtual void setShowGrid ( bool b )
Función que retorna TRUE si la columna puede ser redimencionada por el usuario
bool isColumnStretchable ( int col ) const
Funcion que retorna TRUE si la fila puede ser redimencionada por el usuario
bool isRowStretchable ( int row ) const
Funcion que combina los datos de las filas 1 y 2 (pasadas como argumento)
virtual void swapRows ( int row1, int row2, bool swapHeader = FALSE )
Funcion que combina los datos de las columnas 1 y 2 (pasadas como argumento)
virtual void swapColumns ( int col1, int col2, bool swapHeader = FALSE )
Funcion que combina los datos de las celdas 1 y 2 (pasadas como argumento)
virtual void swapCells ( int row1, int col1, int row2, int col2 )
Funcion que establece, que se comience la edicion en la celda especificada, si replace es TRUE, el dato que
haya previamente sera borrado
virtual void editCell ( int row, int col, bool replace = FALSE )
Señales:
QHeader
Destructor
~QHeader ()
Funcion que añade una nueva seccion con el nombre pasado como argumento y retorna un entero con la
posicion de la nueva seccion para agregarla a la tabla.
int addLabel ( const QString & s, int size = -1 )
Funcion que añade una nueva seccion con el nombre y el icono pasado como argumento y retorna un entero
con la posicion de la nueva seccion para agregarla a la tabla.
int addLabel ( const QIconSet & iconset, const QString & s, int size = -1 )
Funcion que establece si de debe procesar la señal clicked de la tabla, si enable es FALSE, no le dara pelota.
virtual void setClickEnabled ( bool enable, int section = -1 )
Funcion que establece si de debe procesar la señal clicked de la tabla, si enable es FALSE, no le dara pelota.
Funcion que retorna unQRect, con el ancho de una seccion pasada como argumento
QRect sectionRect ( int section ) const
Slots:
Señales:
Esto me parece que ya no tiene sentido explicarlo, porque parece bastante autoexplicativo.
Veamos ahora un ejemplo un poco màs completo, de como podemos combinar varios formularios en
nuestras aplicaciones, y compartir los widgets entre ellos.
ejemplo:
cabecera.h
#ifndef CABECERA_H
#define CABECERA_H
#include <qvbox.h>
#include <qstringlist.h>
class QPushButton;
class QLineEdit;
class QTable;
class QComboBox;
class QFileDialog;
public slots: //funciones de respuesta a las seniales que emiten los widgets
void GetNombre();
void AlmacenarNombre();
void EnviarDatos(int,int,int, const QPoint &);
protected:
QStringList *lstNombres; //los widget que tendra la aplicacion
QStringList *lstAlmacena;
QPushButton *cmd_nombre;
QPushButton *cmd_salvarDatos;
QLineEdit *txt_nombre;
QTable *rejilla;
CDatos *frm_datos;
};
#endif
cabecera.cpp
#include "cabecera.h"
#include <qlabel.h>
#include <qmessagebox.h>
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qtable.h>
#include <qheader.h>
#include <qcombobox.h>
#include <qgrid.h>
#include <qfiledialog.h>
#include <qfile.h>
#include <qtextstream.h>
/**************************************************************************/
/*Creo los widgets de la aplicacion*/
/**************************************************************************/
txt_nombre = new QLineEdit(this, "txt_nombre");
cmd_nombre = new QPushButton (this, "cmd_nombre");
QPushButton *cmd_mostrar = new QPushButton (this, "cmd_mostrar");
cmd_salvarDatos = new QPushButton(this, "cmd_salvarDatos");
QPushButton *cmd_salir = new QPushButton(this, "cmd_salir");
rejilla = new QTable(this,"rejilla");
QHeader *cabecera = rejilla->horizontalHeader();
frm_datos = new CDatos();
/**************************************************************************/
/**************************************************************************/
/* Les asigno las propiedades*/
/**************************************************************************/
cmd_salir->setText("Terminar Aplicacion");
cmd_mostrar->setText("Mostrar nombres almacenados");
cmd_nombre->setText("Almacenar nombre");
cmd_salvarDatos->setText("Salvar los datos");
rejilla->setNumCols(1);
rejilla->setNumRows(0);
cabecera->setLabel(0,"Nombres almacenados",180);
cabecera->setResizeEnabled(FALSE,0);
this->setMinimumSize(500,500);
this->setMaximumSize(1000,1000);
/**************************************************************************/
/**************************************************************************/
/*conecto sus seniales */
/**************************************************************************/
connect (cmd_nombre, SIGNAL (clicked () ), this, SLOT (AlmacenarNombre () ) );
connect (txt_nombre, SIGNAL (returnPressed()), this, SLOT (AlmacenarNombre() ) );
connect (cmd_mostrar, SIGNAL (clicked() ), this, SLOT (GetNombre()) );
connect (cmd_salir, SIGNAL (clicked() ), this, SLOT (close() ) );
connect (cmd_salvarDatos, SIGNAL (clicked() ), frm_datos, SLOT (show() ) );
connect (rejilla , SIGNAL (doubleClicked ( int ,int , int , const QPoint & ) ) , this , SLOT ( EnviarDatos ( int , int ,
int , const QPoint & ) ) );
/**************************************************************************/
}
void CPrincipal::GetNombre()
{
int i = 0;
}
}
void CPrincipal::AlmacenarNombre()
{
lstNombres->append(txt_nombre->text() );
txt_nombre->clear();
}
lstAlmacena->append(dato);
frm_datos->indice++;
if (frm_datos->isShown() )
{
frm_datos->cmb_nombres->clear();
frm_datos->cmb_nombres->insertStringList(*lstAlmacena);
}
}
/************************************************************************************************/
/*Implementacion de la clase CDatos*/
/************************************************************************************************/
titulo->setText("Nombres seleccionados");
cmd_seleccionar->setText("Seleccionar item");
tabla->setNumCols(1);
tabla->setNumRows(1);
cabecera->setLabel( 1 , "Nombres" , 100 );
cmd_salvar->setText("Salvar en archivo");
cerrar->setText("Cerrar");
cmb_nombres->setEditable(TRUE);
indice = 0;
void CDatos::AgregarDato()
{
QString dato = cmb_nombres->currentText();
lstNombres->append(dato);
QStringList::Iterator it = lstNombres->begin();
if (indice >= static_cast<unsigned int> (tabla->numRows() )) tabla->insertRows (1);
for ( unsigned int i = 0; i <= indice; i++ )
{
tabla->setItem ( i-1 , 1 , new QTableItem ( tabla , QTableItem::Never , *it ) );
it++;
}
}
void CDatos::SalvarEnFichero()
{
archivo = new QFileDialog(this);
QStringList *lstSalvar = new QStringList();
archivo->addFilter ( "Archivo de nombres (*.nom *.nombre)" );
archivo->show();
if (dat.open ( IO_Append ) )
{
QTextStream stream (&dat);
for (unsigned int i = 0; i <= static_cast<unsigned int> (tabla->numRows()) -1; i++ )
{
QString cade = tabla->text(i,1);
lstSalvar->append(cade);
}
for ( QStringList::Iterator it = lstSalvar->begin(); it != lstSalvar->end(); it++ )
stream <<"Nombre: " << *it << endl;
}
dat.close();
}
Bueno, espero no haberme excedido con el codigo, el archivo main.cpp, no lo muestro simplemente porque
no ha sido modificado.
En el codigo anterior hay algunos bugs, que luego iremos depurando una vez que mostremos los widgets que
intervienen en el codigo, y lo hayamos estudiado.
Comenzaremos viendo el widget QLabel.h, que sirve para mostrar una etiqueta de texto en la pantalla.
QLabel
Constructores:
Destructores
~QLabel ()
Funciones miembro
Funcion que retorna el texto del label
QString text () const
Funcion que retorna el tipo de alineacion que tiene el texto del label
int alignment () const
Slots
Funcion que trata de cambiar el texto del label, por un numero entero (es como QString::setNum() )
virtual void setNum ( int num )
Funcion que trata de cambiar el texto del label, por un numero doble (es como QString::setNum() )
virtual void setNum ( double num )
Constructor por con un argumento de solo lectura (TRUE solo lectura) (FALSE lectura y escritura)
QComboBox ( bool rw, QWidget * parent = 0, const char * name = 0 )
Destructor
~QComboBox ()
Funcion que rellena el combo, con los datos de array de punteros a cadenas del tipo char **
void insertStrList ( const char ** strings, int numStrings = -1, int index = -1 )
Funcion que remplaza el texto y el pixmap del item segun el indice seleccionado
void changeItem ( const QPixmap & im, const QString & t, int index )
Funcion que cambia el tamaño maximo de caracteres por item que soportara el combo
virtual void setSizeLimit ( int )
Funcion que retorna el tamaño maximo de caracteres por item que soportara el combo
int sizeLimit () const
Funcion que retorna TRUE, si la opcion de los items repetidos esta activa o FALSE en caso contrario
bool duplicatesEnabled () const
Slots:
Señales:
Señal que se activa, cuando el combo es desplegado (igual que la anterior, pero esta soporta el texto)
void activated ( const QString & string )
Señal que se activa, cuando un item del combo esta seleccionado (igual que la anterior, pero esta soporta el
texto)
void highlighted ( const QString & string )
Continuaremos ahora, con el widget QGrid, que sirve para ordenar los objetos dentro de nuestra aplicacion.
QGrid
Constructores
Constructor por defecto, que establece el numero de celdas que tendra, horizontal y verticalmente.
QGrid ( int n, QWidget * parent = 0, const char * name = 0, WFlags f = 0 )
Constructor que establece el numero de celdas que tendra, y si seran verticales o horizontales
QGrid ( int n, Orientation orient, QWidget * parent = 0, const char * name = 0, WFlags f = 0 )
Continuamos con el widget QFileDialog, que es un cuadro de dialogo, para salvar archivos, cargarlos etc...
QFileDialog
Constructores
Destructor
~QFileDialog ()
Funcion que modifica el filtro seleccionado (*.bmp, *.txt *.c etc...) segun el indice de este
virtual void setSelectedFilter ( int n )
Funcion que cambia la seleccion del usuario por un nombre de archivo que especifiquemos
void setSelection ( const QString & filename )
Enumeracion que contiene la forma en que el usuario podra selecionar o ver los archivos o directorios
enum Mode { AnyFile, ExistingFile, Directory, ExistingFiles, DirectoryOnly }
Funcion que cambia la forma en que el usuario podra selecionar o ver los archivos o directorios
void setMode ( Mode )
Funcion que retorna la forma en que el usuario podra selecionar o ver los archivos o directorios
Mode mode () const
Funcion que retorna una direccion de internet en un widget del tipo QUrl.
QUrl url () const
Slots:
Funcion que cambia el directorio
void setDir ( const QString & pathstr )
Funcion que cambia el filtro, siendo este un array de punteros a cadenas de caracteres char **
void setFilters ( const char ** types )
El siguiente widget que veremos, sera el widget QFile usado para el manejo de ficheros en QT
QFile
Constructores
Destructor
~QFile ()
¿Necesita explicacion?
virtual void flush ()
Funcion que retorna TRUE si se llego al final del archivo (es el EOF)
virtual bool atEnd () const
Bueno, parece que terminamos con los widgets, pasemos ahora a explicar el ejemplo nº 3 de este tuto.
Fichero cabecera.h
1):Primero que nada, en el fichero de cabecera cabecera.h, vemos que hemos definido la clase CDatos antes
que la clase CPrincipal, esto es asi, porque necesito que el enlazador tenga una referencia a esta clase para
poder instanciarla desde el formulario principal.
2): En el fichero de cabecera cabecera.h, vemos que en la clase CPrincipal, agregamos un slot nuevo, este
slot (o funcion de respuesta) sirve para cuando en la tabla hagamos dobleclick, se envien los datos al nuevo
formulario.
3): Tambien vemos que hemos cambiado el estado de private a protegido, (protected) esto como sabran es
para que podamos accesar a estos datos desde la otra clase llamada CDatos.
4): Vemos tambien, que hemos agregado otro boton, que sera el que llame al otro formulario, y tambien, dos
lineas màs abajo definimos una instancia de la clase CDatos.
5): He aqui lo nuevo, la clase CDatos, (como se habran dado cuenta ) es una clase para otro formulario.
6): Lo primero que salta a la vista, es que definimos a la clase CPrincipal como amiga de esta, eso es asi,
para de querer poder acceder a los datos de la clase CPrincipal podamos hacerlo.
7): Luego vemos que tenemos 2 slots nuevos, que son para cuando se precione ENTER en el combo o se
haga click en el boton cmd_seleccionar, este slot mandara el dato seleccionado del combo a la tabla.
8): El otro slot, (SalverEnFichero () ) sire como sabran para poder salvar los datos de la tabla en un archivo.
Fichero cabecera.cpp
1): La primera modificacion que tenemos aqui, es la creacion de un boton llamado cmd_salvarDatos, que es
para llamar al otro formulario, luego, vemos que hemos creado una instancia de la clase CDatos, para poder
referenciarla desde el form.
2): Luego de unas lineas, vemos que hemos conectado la señal clicked() del boton cmd_salvarDatos al
formulario frm_datos, y que establecemos como señal de respuesta la funcion show(), esta funcion la
podemos usar tranquilamente (aunque no haya sido previamente definida) gracias a que la clase CDatos,
deriva de QVBox, y este es un widget. Esto significa que la clase CDatos hereda todos los miembros publicos
de la clase QWidget, incluyendo este.
3): Despues conectamos la señal doubleClicked (...) de la rejilla, al slot EnviarDatos (...), que como ya
explique envia los datos al otro formulario. Lo que hay que tener en cuenta, es que los parametros tanto de la
señal, como de la funcion de respuesta (slot) tienen que ser exactamente iguales. Màs adelante explicare
como poder crear nuestras propias señales, derivandolas de otras ya existentes, evitando asi este tipo de
problemas.
4): La funcion de respuesta EnviarDatos(...) no la explicare completa, solamente hay que saver que la funcion
isShown() de la clase QWidget, sirve para saver si el formulario se encuentra visible o no.
5):En el constructor de la clase CDatos, vemos algo muy nuevo, y esto es el QGrid, este widget sirve para
ordenar los widgets de la aplicacion. Todos los widgets que tengamos en el formulario, tendran que
descansar dentro del widget QGrid, para que este pueda acomodarlos.
6): Despues, creamos algunos objetos, y les modificamos las propiedades (nada nuevo).
7): Luego de conectar algunas señales, vemos que creamos un QLineEdit, que contiene el QLineEdit del
combo, y le conectamos la señal returnPressed() al slot AgregarDato (), esto lo hicimos, porque el
QComboBox no tiene ninguna señal, returnPressed, y ya que el combo tiene un widget QLineEdit asociado,
aprovechamos la señal de este, para usarla en nuestro form (ingenioso ¿no?).
8): La funcion AgregarDato, no la explicare porque creo que no merece la pena, ahun asi si tienen alguna
duda, manden un mail, y tratare de ayudarlos en lo que pueda.
9): Y llegamos a la ultima funcion, esta funcion, como se habran dado cuenta (NO FUNCA!!!), eso se los dejo
como tarea para que investiguen un poco, y aprendan. (Ya escucho los insultos jeje). Una pista, si se fijan
bien, el problema es una pavada, y esta asociado con el nombre del archivo.
Demos ahora un ejemplo de las señales, estas se encuentran en el fichero de cabecera qsignal.h, que a su
vez, esta heredado por QWidget, osea por casi todos los widgets.
#include <qobject.h>
public:
MiClase();
int valor() const { return val ;}
public slots:
void setValor (int);
signals:
CambiaValor(int);
private:
int val;
};
Este pequeño ejemplo, define una clase llamada MiClase, y crea una señal, que sera emitida cuando la
funcion de respuesta setValor sea llamada, y luego de comprobar una condicion critica. Para emitir una señal,
se usa (logico) la funcion emit. Atencion: es altamente recomendable, separar la definicion de la clase que
creamos (archivo .h) de la implementacion (archivo .cpp), para que funcione correctamente
Sabiendo esto, nosotros podemos definir tantas señales como queramos dentro de nuestra clase, para luego
poder utilizarlas a nuestro antojo (Llora el VC++ y visual script).
pongamos un ejemplo un poco màs claro, y de paso mostrare otro widget, màs que interesante el
QGridLayout.
ejemplo:
cabecera.h.
#ifndef CABECERA_H
#define CABECERA_H
#include <qwidget.h>
class QPushButton;
class QLabel;
class CVentana : public QWidget
{
Q_OBJECT
public:
CVentana (QWidget *parent = 0, const char *name = 0);
public slots:
void Mensaje ();
signals:
void Sig_Mensaje(const QString & );
private:
QPushButton *boton;
QLabel *label;
QString contador;
int i;
};
#endif
cabecera.cpp.
#include "cabecera.h"
#include <qpushbutton.h>
#include <qmessagebox.h>
#include <qlabel.h>
#include <qlayout.h> //este fichero nunca lo vimos :)
i = 0;
connect (this, SIGNAL (Sig_Mensaje(const QString &) ), label, SLOT(setText(const QString &) ) );
connect (boton,SIGNAL(clicked() ), this, SLOT (Mensaje() ) );
connect (salir,SIGNAL(clicked() ), this, SLOT (close () ));
}
void CVentana::Mensaje()
{
static const QString msg = "Veces que se pulso el boton = ";
i++;
contador = contador.setNum(i,10);
emit Sig_Mensaje( msg + contador );
El fichero principal, no lo muestro, porque por ahora sigue siendo siempre lo mismo. Pasemos a ver como
funciona la cosa, por ahora recomiendo olvidarse de QGridLayout, este widget ya lo veremos.
1): En el fichero cabecera.h, lo primero que salta a la vista, es la funcion de respueste Mensaje(), este no es
màs que un slot, que lo asociaremos a la señal clicked() del boton salir.
2): Lo segundo que se ve "raro", es la definicion de la seccion signals, esta seccion, (al contrario de lo que
pueden decir muchos), no es nada especial, solamente tenemos que tener en cuenta, que NO esta permitido
especificarle un tipo de acceso, (public, private, friend etc..), y que los parametros pasados tienen que ser
IGUALES a las funciones de respuesta. Aqui, definimos las señales propias, que queremos conectar a los
diferentes widgets de la aplicacion, es este caso, conectamos la señal Sig_Mensaje(const QString &) al slot
setText(const QString &) del widget QLabel, para que este muestre el texto, que luego le pasaremos como
argumento a la señal.
Los slots pueden ser de otros widgets, o nuestros, mientras que tengan los mismos parametros no hay
problema.
3): Luego, en el fichero cabecera.cpp, vemos que conectamos la señal Sig_Mensaje(...) de esta manera:
connect ( this, SIGNAL (Sig_Mensaje(const QString & ) ), label, SLOT (setText (const QString & ) ) );
Lo primero que tenemos que decirle a connect, es donde esta definida la señal que queremos conectar, en
este caso, es en nuestra clase, si estuviese en otra clase, tendriamos que especificarlo.
4): Luego, en la funcion de respuesta Mensaje(), vemos la funcion emit, esta funcion simplemente lanza la
señal con los parametros que tenga, para que el widget que este conectado a ella, la procese.
Tenemos que ver esto, como si fuera algo simple, ya que no tiene mayores complicaciones. Puesto que el
compilador lo unico que hace internamente es remplazar los parametros de la funcion de respuesta asociado
a la señal, por los parametros pasados como argumentos al momento de emitirse la señal (con emit ).
(remplaza una funcion por otra :) )
espero, que no se les complique, aunque es muy facil, aun asi, si hay dudas escriban y los ayudare.
Expliquemos ahora, que es eso de QGridLayout, este widget es uno que vamos a usar bastante, ya que nos
permite alinear los items de manera ordenada y facil
QGridLayout
Constructores
Constructor con argumentos, los cuales son el numero de filas y columnas que tendra, y el espaciado entre
ellas, y finalmente el nombre del widget.
QGridLayout ( int nRows = 1, int nCols = 1, int spacing = -1, const char * name = 0 )
Constructor con argumentos, los cuales son parentLayout, es el widget padre, (sobre el cual descansara), el
resto de los parametros son los mismos que antes.
QGridLayout ( QLayout * parentLayout, int nRows = 1, int nCols = 1, int spacing = -1, const char * name = 0 )
Destructor
~QGridLayout ()
Funcion que retorna un QSize, con el tamaño minimo necesitado por la rejilla.
virtual QSize minimumSize () const
Funcion que retorna un QSize, con el tamaño maximo necesitado por la rejilla.
virtual QSize maximumSize () const
Funcion que establece el estrecho de una fila los parametros son la fila, y el tmaño que queramos
virtual void setRowStretch ( int row, int stretch )
Funcion que establece el estrecho de una columna los parametros son la columna, y el tmaño que queramos
virtual void setColStretch ( int col, int stretch )
Funcion que retorna el ancho (estrecho) de una fila, los argumentos son el numero de fila
int rowStretch ( int row ) const
Funcion que retorna el ancho (estrecho) de una columna, los argumentos son el numero de columna
int colStretch ( int col ) const
Funcion que establace el alto de una fila, los parametros son la fila, y el tamaño minimo especificado.
void setRowSpacing ( int row, int minSize )
Funcion que establace el alto de una columna, los parametros son la columna, y el tamaño minimo
especificado.
void setColSpacing ( int col, int minSize )
Funcion que retorna un QRect, con la geometria de la celda, entre la fila y la columna especificada.
QRect cellGeometry ( int row, int col ) const
Funcion para poder combinar un rango de filas o columnas o ambos. (Muy recomendable) los parametros
son:
QWidget *w = El wiget que queremos acomodar
int fromRow = desde la fila
int toRow = hasta la fila
int fromCol = desde la columna
int toCol = hasta la columna
int alignment = 0 (centrado) = contiene los valores de Qt::AlignmentFlags.
void addMultiCellWidget ( QWidget * w, int fromRow, int toRow, int fromCol, int toCol, int alignment = 0 )
Enumeracion que contiene el tipo de alineacion que queramos. Los tipos son:
QGridLayout::TopLeft -
QGridLayout::TopRight -
QGridLayout::BottomLeft -
QGridLayout::BottomRight -
¿Necesita explicacion?
enum Corner { TopLeft, TopRight, BottomLeft, BottomRight }
Funcion que alinea, los widget dentro del QGridLayout, con la alineacion previamente vista.
void setOrigin ( Corner c )
Funcion que retorna una enumeracion Corner, con la alineacion que estamos usando actualmente.
Corner origin () const
Vamos a ver ahora, un ejemplo un poco màs avanzado, tratemos de combinar las funciones de la libreria QT,
con las funciones de alguna otra libreria, (esto es como para recalcar un poco la compatibilidad de datos de
QT) en este caso Postgresql. No es realmente necesario hacer esto, ya que la libreria trae incorporado los
drivers y las clases para el proceso de las bases de datos màs conocidas y utilizadas, pero aun asi, lo
haremos para mostrar como combinar las funciones y mostrar un poco màs sobre las señales.
Como vamos a utilizar otras librerias, para no complicarnos las cosas he decidido entregar los fuentes,
utilizando el kdevelop.
Ejemplo:
Fichero bdatos.h
#ifndef BDATOS_H
#define BDATOS_H
#include <qwidget.h>
#include <pgsql/libpq-fe.h>
class QStringList;
class BDatos : public QWidget
{
Q_OBJECT
public:
BDatos(QWidget *parent = 0, const char *name = 0);
BDatos(QString dbName, QWidget *parent = 0, const char *name = 0);
~BDatos() { desconecta(); }
signals:
void Mensaje (const QString &);
void ConeccionCerrada();
void EnviarDatos(QStringList &);
public slots:
void GetDatos();
void desconecta ();
void conecta(QString dbname);
void conecta();
private:
#endif
Fichero bdatos.cpp
#include "bdatos.h"
#include <qmessagebox.h>
#include <qstringlist.h>
/**************************************Constructor **********************************/
BDatos::BDatos(QWidget *parent, const char *name ) : QWidget (parent,name)
{
nBase = (nBase != "oxygen" && nBase != "") ? nBase : "oxygen";
conecta (nBase);
}
Fichero interface.h
#ifndef INTERFACE_H
#define INTERFACE_H
#include <qwidget.h>
#include "bdatos.h"
class QTable;
class CVentana : public QWidget
{
Q_OBJECT
public:
CVentana( QWidget *parent = 0, const char *name = 0 );
public slots:
void RellenarLista(QStringList &);
void Msg(const QString &);
void LimpiarRejilla();
private:
BDatos *dat;
QTable *tabla;
signed int indice;
};
#endif
Fichero interface.cpp
#include <qpushbutton.h>
#include <qlayout.h>
#include <qmessagebox.h>
#include <qtable.h>
#include <qheader.h>
#include "interface.h"
//Tengo que crear el QHeader aqui, para que quede correctamente alineado con la tabla
QHeader *cabecera = tabla->horizontalHeader();
cabecera->setLabel(0,"Nombre");
cabecera->setLabel(1,"Apellido");
cabecera->setLabel(2,"Direccion");
cabecera->setLabel(3,"Telefono");
cabecera->setLabel(4,"E-mail");
connect (dat , SIGNAL (Mensaje(const QString &) ), this, SLOT ( Msg (const QString &) ) );
connect (cerrarConeccion, SIGNAL ( clicked () ) , dat, SLOT (desconecta() ) );
connect (limpiarRejilla, SIGNAL (clicked() ), this, SLOT (LimpiarRejilla() ) );
connect (conectar, SIGNAL (clicked() ), dat, SLOT (conecta() ) );
connect (juntarDatos, SIGNAL (clicked() ), dat, SLOT (GetDatos( ) ) );
connect (dat, SIGNAL (EnviarDatos(QStringList& )), this, SLOT (RellenarLista(QStringList& ) ) );
connect (salir, SIGNAL (clicked() ), this, SLOT (close() ) );
/***************************************************************************************************/
void CVentana::LimpiarRejilla( )
{
indice = 0;
tabla->setNumRows (0);
Fichero main.cpp
#include <qapplication.h>
#include "interface.h"
Como vemos hemos creado un widget llamado BDatos, para el manejo de las funciones basicas de la libreria
postgresql. Pasemos a analizar el fichero bdata.h
bdata.h
1): el primer paso, es incluir los archivos de cabecera, que necesitemos, en este caso incluimos qwidget, para
derivar la clase BDatos directamente de ella, y luego incluimos el archivo de cabecera pgsql/libpq-fe.h, para
poder utilizar las funciones basicas de la libreria.
2): Luego, lo que resalta es que hemos definido 2 constructores diferentes, esto es posible de hacer, con
cualquier clase que derivemos de QWidget, lo unico que tenemos que tener en cuenta es que los parametros
que queramos agregarles tienen que ser puestos primero, y luego pasarle los parametros por defecto
(Qwidget *parent = 0, const char *name = 0) .
3): luego vemos que hemos definido un area para las señales, las cuales son:
void Mensaje (const QString &) que sirve para enviar un mensaje con los estados de la coneccion y demas.
void ConeccionCerrada() que sera emitida, ni bien nos desconectemos de la base de datos.
void EnviarDatos(QStringList &) que servira, para enviarnos los datos extraidos de la base de datos.
4):Despues, vemos que hemos definido varios slots, que sirven para:
void GetDatos(); cuando lo llamemos, este slot, lanzara la señal, con los datos extraidos
void desconecta (); este slot, nos desconecta de la base de datos
void conecta(QString dbname); este slot, nos conecta con la base de datos
void conecta(); Y este slot, tambien sirve para conectarnos, solamente esta sobrecargado.
5): Luego en la seccion private, solamente nos queda declarar las variables que usaremos en la clase.
bdata.cpp
Aqui, no explicare todo el codigo, puesto que este pretende ser un tutorial de QT, no de postgresql, pero si
las funciones màs relevantes.
inteface.h
a esta altura, no me parece interesante explicar este fichero solamente diremos para que son los slots que
contiene.
void RellenarLista(QStringList &); este slot, simplemente muestra los datos en la tabla.
void Msg(const QString &); el el slot, que mostrara los mensajes de la clase BDatos.
void LimpiarRejilla(); simplemente limpia la rejilla.
inteface.cpp
1): primero que nada, vemos que en el constructor cramos un QGridLayout, para ordenar los widgets dentro
del formulario, y luego creamos algunos botones e iniciamos el objeto dat, que es nuestro widget antes
creado.
2): luego, vemos que posicionamos los widgets dentro del formulario, con la ayuda de un QGridLayout.
3): Luego preparo la rejilla, asignando los nombres a las columnas, y el ancho de las mismas.
4): Luego vemos, que las señales, las conectamos como siempre. El resto de las funciones, no las explicare,
porque creo que no merecen una mayor explicacion.
Algo a lo que deberemos acostumbrarnos, es a crear siempre dos ficheros por clase, ya que de esta manera,
sera màs facil manejar el codigo.
Tratamiento de imagenes
Veamos ahora, como podemos cargar y modificar imagenes en nuestros programas, primero veremos el
widget QPixmap. Pondre un ejemplo bastante basico, y luego lo explicare paso a paso.
Ejemplo:
Fichero cabecera.h
#ifndef IMAGENES.H
#define IMAGENES_H
#include <qwidget.h>
class QPixmap;
class QLabel;
class QPushButton;
#endif
Fichero cabecera.cpp
#include <qpixmap.h>
#include <qfiledialog.h>
#include <qpushbutton.h>
#include <qlayout.h>
#include <qlabel.h>
#include "imagenes.h"
rejilla->addWidget (cargarImagen,0, 0 );
rejilla->addWidget (mostrarImagen, 0, 1);
rejilla->addWidget (salir, 0, 2 );
rejilla->addMultiCellWidget (label, 1 , 2 , 0 , 4 );
void Ventana::cargaImagen()
{
*nombre_imagen = QFileDialog::getOpenFileName ("/home",
"imagenes (*.png *.jpg *.xpm)",
this,
"Abrir imagen",
"seleccionar archivo");
imagen = new QPixmap(*nombre_imagen);
}
void Ventana::muestraImagen()
{
label->setPixmap (*imagen);
}
Fichero main.cpp
#include <qapplication.h>
#include "imagenes.h"
Como podemos ver, todo el codigo mostrado aqui, es realmente relevante, solamente nos tenemos que
enfocar en la declaracion de QPixmap *imagen en la definicion de la clase Ventana, y en imagen = new
QPixmap (*nombre_imagen), que carga una imagen pasada como argumento en el constructor, luego
simplemente en la funcion muestraImagen(), le asigno la imagen antes cargada al label, como buena noticia
es que las imagenes se pueden asignar a casi CUALQUIER WIDGET DE LA LIBRERIA.
QPixmap
Constructor con el ancho, el alto, la profundidad de colores (8,16 o 32 BYTES), y el modo de optimizacion
QPixmap ( int w, int h, int depth = -1, Optimization optimization = DefaultOptim )
Constructor con el nombre de la imagen, el formato por defecto, y el modo de conversion (ya lo veremos)
QPixmap ( const QString & fileName, const char * format, int conversion_flags )
Constructor con un const char *[], que contiene la imagen en si en formato crudo.
QPixmap ( const char * xpm[] )
Constructor copia
QPixmap ( const QPixmap & pixmap )
Destructor
~QPixmap ()
Funcion que pinta la imagen en el widget especificado., xofs e yofs son las coordenadas ( ¡que funcion!
¿no? )
void fill ( const QWidget * widget, int xofs, int yofs )
Funcion que pinta la imagen en el widget especificado, en las coordenadas pasadas por QPoint
void fill ( const QWidget * widget, const QPoint & ofs )
Funcion que redimenciona el tamaño de la imagen segun el QSize pasado como argumento
void resize ( const QSize & size )
Funcion que cambia la mascara de bit de la imagen, por un QBitmap pasado como argumento.
void setMask ( const QBitmap & newmask )
Funcion que retorna TRUE, si la imagen tiene activado un canal alfa on una mascara
bool hasAlpha () const
Funcion que retorna TRUE si la conversion a QImage fue realizada con exito
bool convertFromImage ( const QImage & image, ColorMode mode = Auto )
bool convertFromImage ( const QImage & img, int conversion_flags )
Funcion que retorna un numero unico, que identifica el contenido del pixmap
int serialNumber () const
Funcion que retorna la profundidad de colores por defecto que tiene la imagen
int defaultDepth ()
Funcion que retorna un QPixmap, con la imagen seleccionada como argumento, (la imagen seleccionada
tiene que estar en formato texto)
QPixmap fromMimeSource ( const QString & abs_name )
Funcion que graba el contenido de la ventana, y retorna un QPixmap con el contenido recien grabado.
QPixmap grabWindow ( WId window, int x = 0, int y = 0, int w = -1, int h = -1 )
Funcion que graba el contenido del widget, y retorna un QPixmap con el contenido recien grabado.
QPixmap grabWidget ( QWidget * widget, int x = 0, int y = 0, int w = -1, int h = -1 )
Funcion que retorna un const char *, con los datos de la imagen pasada como argumento
const char * imageFormat ( const QString & fileName )
Por el momento no mostrare ningun otro ejemplo de tratamiento de imagenes, porque llevaria varias paginas
de este tutorial, pero si las iremos viendo y explicando a traves de otros ejemplos y en futuros tutoriales.
Menues:
Los famosos menues, existieron desde el comienzo de las aplicaciones como todos sabemos representan
una forma ordenada de crear botones con un argumento en comun. Podemos distinguir dos tipos de menues
diferentes en las aplicaciones, los primeros son los "PopupMenus", que existen en casi todas las
aplicaciones, y los segundos son los "ContextMenus", que son los famosos menues contextuales que salen
por ejemplo cuando pulsamos el boton derecho del mouse sobre un area de la aplicacion. Pondre un ejemplo
de como crear algunos menues, y luego lo explicaremos.
Ejemplo:
Fichero formulario.h
#ifndef FORMULARIO_H
#define FORMULARIO_H
#include <qwidget.h>
#include <qmenubar.h>
class QTable;
class QPixmap;
class QLabel;
class QLCDNumber;
class QProgressBar;
class QTimeEdit;
class QDial;
class QListView;
public:
public slots:
void InsertarImagen();
void InsertarCombo();
void InsertarCheck();
void InsertarTexto();
/*----------------------------------------> Tipos de widgets a insertar*/
void InsertarLabel();
void InsertarLCD();
void InsertarProgressBar();
void InsertarTimeEdit();
void InsertarDial();
void InsertarListView();
/************************************************************************/
private:
QMenuBar *Menu;
QTable *tabla;
QPixmap *imagen;
int indice;
};
#endif
Fichero formulario.cpp
#include <qpopupmenu.h>
#include <qtable.h>
#include <qlayout.h>
#include <qpixmap.h>
#include <qstringlist.h>
#include <qheader.h>
/************para InsertarWidget()***************/
#include <qdial.h>
#include <qlistview.h>
#include <qdatetimeedit.h>
#include <qprogressbar.h>
#include <qlcdnumber.h>
#include <qlabel.h>
/***********************************************/
#include "formulario.h"
/* Creo el menu archivo, con los datos que tendra y defino tambien los slots que usara*/
QPopupMenu *archivo = new QPopupMenu;
archivo->insertItem("Limpiar rejilla", this , SLOT (LimpiarCeldas() ) );
archivo->insertSeparator();
archivo->insertItem ("Salir", this , SLOT (close() ) , CTRL+Key_S );
/*************************************************************************************/
/***** Ahora creo el menu insertar, de la misma manera que lo hice anteriormente *****/
QPopupMenu *insertar = new QPopupMenu;
insertar->insertItem ("&Imagen", this, SLOT (InsertarImagen () ), CTRL+Key_I );
insertar->insertItem ("&ComboBox", this, SLOT (InsertarCombo () ), CTRL+Key_C );
insertar->insertItem ("C&heckBox", this, SLOT (InsertarCheck () ), CTRL+Key_H );
insertar->insertItem ("Un &Texto", this, SLOT (InsertarTexto () ), CTRL+Key_T );
insertar->insertItem ("Un Widget->", widgets, CTRL+Key_W );
/*************************************************************************************/
/*********Ahora inserto todos los submenues ( archivo y insertar ) al Menu principal ( Menu )********/
Menu->insertItem ("&Archivo", archivo );
Menu->insertItem ("&Insertar cosas", insertar );
/****************************************************************************************************/
rejilla->addMultiCellWidget ( tabla, 1 , 19 , 0 , 0 );
void CFormulario::InsertarImagen()
{
if (indice >= tabla->numRows() )
{
tabla->setNumRows(indice + 1 );
tabla->repaint();
}
tabla->setPixmap ( indice , 0 , *imagen );
tabla->adjustRow(indice);
indice ++;
}
void CFormulario::InsertarCombo()
{
void CFormulario::InsertarCheck()
{
if (indice >= tabla->numRows() )
{
tabla->setNumRows(indice + 1 );
tabla->repaint();
}
void CFormulario::InsertarTexto()
{
if (indice >= tabla->numRows() )
{
tabla->setNumRows(indice + 1 );
tabla->repaint();
}
void CFormulario::InsertarLabel()
{
if (indice >= tabla->numRows() )
{
tabla->setNumRows(indice + 1 );
tabla->repaint();
}
label = new QLabel("<font color=#0000ff face=Akaash>Texto del label</font>", this , "label");
tabla->setCellWidget (indice, 0 , label);
indice ++;
void CFormulario::InsertarLCD()
{
if (indice >= tabla->numRows() )
{
tabla->setNumRows(indice + 1 );
tabla->repaint();
}
lcd = new QLCDNumber(this);
tabla->setCellWidget (indice, 0 , lcd );
void CFormulario::InsertarProgressBar()
{
if (indice >= tabla->numRows() )
{
tabla->setNumRows(indice + 1 );
tabla->repaint();
}
barra = new QProgressBar (this, "barra");
void CFormulario::InsertarTimeEdit()
{
if (indice >= tabla->numRows() )
{
tabla->setNumRows(indice + 1 );
tabla->repaint();
}
timeedit = new QTimeEdit (this, "timeedit");
void CFormulario::InsertarDial()
{
if (indice >= tabla->numRows() )
{
tabla->setNumRows(indice + 1 );
tabla->repaint();
}
dial = new QDial (this, "dial");
void CFormulario::InsertarListView()
{
QListViewItem *item;
if (indice >= tabla->numRows() )
{
tabla->setNumRows(indice + 1 );
tabla->repaint();
}
lista = new QListView(this, "lista");
lista->addColumn ("Nombre: ");
lista->addColumn ("Apellido");
void CFormulario::LimpiarCeldas()
{
tabla->setNumRows(0);
tabla->repaint();
indice = 0;
}
CFormulario::~CFormulario()
{
delete Menu;
delete tabla;
delete imagen;
delete label;
delete lcd;
delete barra;
delete timeedit;
delete dial;
delete lista;
}
El fichero principal.cpp, (el main) no lo muestro porque por el momento es el mismo siempre.
Pasemos a explicar un poco como funcionan los menues, para esto vemos la declaracion del fichero de
cabecera (en formulario.h) qmenubar.h, este fichero se encarga de "preparar los menues", es como un
contenedor, que dentro puede contener otros "submenues" llamados qpopupmenu, que es endonde
almacenaremos los datos de un ambito en particular.
ej:
Estos son los submenues o QPopupMenu dentro de los cuales agruparemos los botones que queramos.
QPopupMenu *archivo = new QPopupmenu;
QPopupMenu *edicion = new QPopupmenu;
QPopupMenu *ver = new QPopupmenu;
QPopupMenu *insertar = new QPopupmenu;
QPopupMenu *formato = new QPopupmenu;
QPopupMenu *etc = new QPopupmenu;
donde archivo es el identificador del submenu, y insertItem es la funcion encargada de insertar un item
( logico no? ), los parametros de la funcion InsertItem son los siguientes:
1): El texto que le queremos poner (lo que queremos que diga), aqui le podemos poner el texto, o alguna
imagen, o ambos ( ya mostrare las funciones )
2): el segundo parametro es la clase donde se almacenara, como se va haciendo costumbre lo ponemos en
nuestra clase con this.
3): El tercer parametro es un poco màs dificil de explicar, pero no se preocupen que es facil. Como se daran
cuenta, al boton del menu se le asocia inmediatamente una funcion de respuesta, pero en ninguna parte del
codigo lanzamos ninguna señal. Esto se debe a que el widget QPopupMenu, solamente soporta cuatro
señales, las cuales son:
1): activated (int id ) esta señal, se lanza cuando el boton se activa (cuando es pulsado)
2): highlighted (int id ) esta señal, se lanza cuando el boton se ilumina (cuando es apuntado con el mouse o
con el teclado)
3): aboutToShow () esta señal, se lanza justo despues que el menu es desplegado
4): aboutToHide () esta señal, se lanza justo despues que el menu es ocultado
La señal que por defecto conectamos siempre es activated (int id), como se daran cuenta, tampoco le
pasamos el id en la funcion de respuesta, esto se deve a que la funcion esta sobrecargada.
Les dejo como tarea, (si quieren hacerlo) el crear una funcion, para poder interactuar, y poder atender las
señales de los items del codigo anterior, es facil, sobre todo si recuerdan, que casi todos los widgets derivan
de la clase base "abstracta" QWidget.
Destructor
~QMenuBar ()
Funcion, que inserta un item, como imagen, en un QPopupMenu pasado como argumento
int insertItem ( const QPixmap & pixmap, QPopupMenu * popup, int id = -1, int index = -1 )
Funcion, que inserta un item, con el icono y la imagen en el QPopupMenu pasado como argumento.
int insertItem ( const QIconSet & icon, const QPixmap & pixmap, QPopupMenu * popup, int id = -1, int index =
-1 )
Funcion, que borra un item del menu, segun el id pasado como argumento
void removeItem ( int id )
Funcion, que RETORNA true, si el item con el id pasado como argumento esta abilitado
bool isItemEnabled ( int id ) const
Funcion, que retorna TRUE, si el item con el id pasado como argumento es visible.
bool isItemVisible ( int id ) const
Señales:
Bueno, esto fue todo por el momento, pero no crean que terminara aqui, pronto creare otro tutorial, un poco
màs avanzado, que explicara el tratamiento de las imagenes en QT, y como crear formularios midi y hablare
un poco sobre el manejo de treads y procesos.
Pos: Disculpen por las faltas de ortografia, pero la culpa la tiene mi teclado, que es yanquee y no entiende
castellano.
Saludos a todos, y si alguien sabe programar en qt, y le interesa traducir la documentacion de la libreria, por
fabor avisenme que con gusto los ayudare.