Arriba

Uso Simple De Layouts

En el artículo anterior vimos como colocar componentes en una ventana de manera absoluta. A pesar de parecer tan fácil, tiene el inconveniente de la apariencia de los controles cuando se redimensiona la ventana. Los layouts vienen a suplir esta carencia, facilitándole al programador la labor de acomodar la apariencia sin tener que codificar algo. Lenguajes como Java hace uso intensivo de layouts pero programadores de otros lenguajes como Visual Basic o Delphi puede parecerle extraño o complicada la manera de colocar los objetos usando layouts; la primera vez que vi layouts fue haciendo un programa en Java usando AWT y terminé frustrado el primer día porque no se colocaban los controles como esperaba, luego de unos días de prácticas conseguí entender su uso y ahora es parte fundamental en mis diseños de interfaces usando Qt, porque Java... no gracias.

El toolkit Qt nos provee varios layouts para facilitar la ubicación de los componentes, incluso provee contenedores como los QHBox y QVBox que consumen menos recursos que los layouts y se emplean cuando no se requere mayor cosa al momento de colocar los componentes. De todos los layouts que provee Qt solo explicaré el QGridLayout, ya que al fin y al cabo se amolda a cualquier situación y puede ser usado para cualquier interfaz. Si el lector quiere, puede buscar en la documentación de Qt la ayuda de los otros layouts ya que todos derivan de la misma clase base QLayout.

El QGridLayout es semejante a usa hoja de cálculo pues está dividido en filas y columnas. La unión de cada fila y columna forman una celda y una celda puede abarcar varias columnas y/o filas si se unen. Cada objeto que es creado luego es añadido al layout indicándole la fila y columna a ocupar.

Para poder diseñar la apariencia se debe delimitar la ubicación de los controles a usar. Siguiendo el mismo ejemplo del artículo anterior, tenemos entoces diez botones donde cada botón podríamos considerar que ocupa una celda a excepción del "0" que ocupa tres columnas en la misma fila, por lo que necesitamos crear un QGridLayout de cuatro filas por tres columnas. Lo demás es simple: crear los objetos y añadirlos al layout indicando su posición. Nuestro código quedaría así:

Archivo KMiMainWindow.cpp
#include "KMiMainWindow.h" #include <kpushbutton.h> // Encabezados añadidos #include <qlayout.h> /****************************************************************************** * Constructor de la clase. * ******************************************************************************/ KMiMainWindow::KMiMainWindow(QWidget *parent, const char *name) : KMainWindow(parent, name) { KPushButton *pb; setCaption("MiMainWindow"); setGeometry(0, 0, 125, 165); // Los parámetros del constructor del layout son: // QGridLayout(pariente, filas, columnas, margen, espaciado, nombre) QGridLayout *gl = new QGridLayout(this, 4, 3, 5, 5, "layout"); // Ahora creamos los 10 botones y los ubicamos en el layout. // Los parámetros del constructor del botón son: // KPushButton(etiqueta que mostrará el botón, pariente, nombre) pb = new KPushButton("1", this, "1"); pb->setMinimumSize(35, 35); gl->addWidget(pb, 0, 0); pb = new KPushButton("2", this, "2"); pb->setMinimumSize(35, 35); gl->addWidget(pb, 0, 1); pb = new KPushButton("3", this, "3"); pb->setMinimumSize(35, 35); gl->addWidget(pb, 0, 2); pb = new KPushButton("4", this, "4"); pb->setMinimumSize(35, 35); gl->addWidget(pb, 1, 0); pb = new KPushButton("5", this, "5"); pb->setMinimumSize(35, 35); gl->addWidget(pb, 1, 1); pb = new KPushButton("6", this, "6"); pb->setMinimumSize(35, 35); gl->addWidget(pb, 1, 2); pb = new KPushButton("7", this, "7"); pb->setMinimumSize(35, 35); gl->addWidget(pb, 2, 0); pb = new KPushButton("8", this, "8"); pb->setMinimumSize(35, 35); gl->addWidget(pb, 2, 1); pb = new KPushButton("9", this, "9"); pb->setMinimumSize(35, 35); gl->addWidget(pb, 2, 2); pb = new KPushButton("0", this, "0"); pb->setMinimumSize(35, 35); gl->addMultiCellWidget(pb, 3, 3, 0, 2); }

En el constructor del QGridLayout le indicamos el número de filas y columnas que vamos a necesitar, en nuestro caso 4x3. También le indicamos dos parámetros que nos ayudarán en el uso de los layouts: el margen y el espaciado. El margen es la separación que hay entre en el elemento padre y el layout mientras que el espaciado es la separación entre los componentes colocados en el layout. La siguientes tablas ilustran los cuatro parámetros usados.

1 2 3
4 5 6
7 8 9
0
 
1   2   3
4   5   6
7   8   9
0

La línea azul indica donde se coloca el layout con respecto al objeto padre, que puede ser una ventana, la línea roja muestra el borde del layout y las líneas negras son los bordes de los controles. El ejemplo de la izquierda muestra un margen y un espaciado de 0 mientras que el segundo muestra un margen de 10 y un espaciado de 10. El margen viene siendo la separación entre la línea roja y la azul mientras que el espaciado es la separación entre las líneas negras de los controles. El ejemplo fue hecho usando tablas HTML así que la apariencia puede variar de un navegador a otro así como también puede parecer que la separación de las filas no es la misma que la de las columnas. Es recomendable ir cambiando los valores para ir notando como cambia el diseño, así se tendrá un mejor aprendizaje.

Cada vez que se crea un control lo añadimos al layout por medio del método addWidget y le pasamos el puntero del objeto a añadir así como la fila y la columna donde será ubicado. Si el control es multicolumna y/o multifila se usa el método addMultiCellWidget; este método acepta cuatro parámetros además del objeto padre: fila inicial, fila final, columna inicial y columna final. En el caso del "0", que se expande 3 columnas, indicamos 0 como la columna inicial y 2 como la columna final, mientras que los valores para las filas son las mismas ya que no hay expansión de filas, por eso ambos valores son 3.

Una vez compilado el programa y ejecutado obtenemos una ventana parecida a la del artículo anterior; la diferencia está al momento de redimensionar la ventana. Si redimensionamos la ventana obtenemos algo parecido a la siguiente imagen, donde observamos que los controles son redimensionados proporcionalmente para llenar toda la ventana; ésto es hecho automáticamente por el layout. Si queremos que el crecimiento no sea proporcional, podemos configurarlo cambiando los parámetros de stretch de cada columna y fila.

Uso simple de layouts

En la imagen se puede apreciar que el resultado obtenido es mucho más estético que en el caso de la colocación absoluta cuando se redimensiona. En realidad, una vez que se domina el uso de layouts difícilmente se vuelva a usar el modo absoluto para ubicar los controles en una ventana o control padre.