Al crear una aplicación, puede que quieras colocar más de un widget dentro de
una ventana. Nuestro primer ejemplo "hello world" únicamente usaba un widget,
por lo que pudimos usar set
para especificar un widget containerChild
(contenedor de hijo) para window
, o usar containerAdd
(Añade contenedor)
para empaquetar el widget en la ventana. Pero cuando quieres poner más de un widget en
una ventana, cómo puedes controlar la posición del mismo? Para esto sirve el
empaquetado.
La mayoría del empaquetado se hace creando cajas. Hay contenedores invisibles de widgets en los que podemos empaquetarlos. Los encontramos de dos tipos: Una caja horizontal y una caja vertical. Al empaquetar los objetos en una caja horizontal, los objetos se insertan horizontalmente de izquierda a derecha o de derecha a izquierda dependiendo de la llamada utilizada. En la caja vertical, los widgets se empaquetan de arriba abajo o viceversa. Puedes usar cualquier combinación de cajas dentro o junto a otras para crear el efecto deseado.
Para crear una nueva caja horizontal, usamos hBoxNew
, y para una caja vertical,
vBoxNew
. Ambos usan un parámetro de tipo Bool
y otro de
tipo Int
. El primer parámetro dará espacios iguales a cada widget hijo si se le pasa el
valor True y el segundo establece el número de píxeles a colocar 'por defecto' entre los hijos.
Las funciones boxPackStart
y boxPackEnd
se usan para colocar objetos dentro de esos
contenedores. La función boxPackStart
colocará los widgets de arriba abajo en una caja vertical, VBox
, y de izquierda a derecha en una caja horizontal. boxPackEnd
hará lo opuesto, de abajo arriba en una caja vertical VBox
, y de derecha a izquierda en una
HBox
.
Mediante estas funciones podremos justificar por la derecha o por la izquierda nuestros widgets y mezclarlos
de modo que obtengamos el efecto deseado. En la mayoría de nuestros ejemplos usaremos boxPackStart
.
Un objeto opuede ser otro contenedor o un widget. De hecho, muchos widgets son a la vez contenedores, incluyendo
button
,(botón) pero habitualmente sólo usamos una label
(etiqueta) dentro de un button
.
import Graphics.UI.Gtk main :: IO () main = do initGUI window <- windowNew hbox <- hBoxNew True 10 button1 <- buttonNewWithLabel "Button 1" button2 <- buttonNewWithLabel "Button 2" set window [windowDefaultWidth := 200, windowDefaultHeight := 200, containerBorderWidth := 10, containerChild := hbox] boxPackStart hbox button1 PackGrow 0 boxPackStart hbox button2 PackGrow 0 onDestroy window mainQuit widgetShowAll window mainGUI
Usando boxPackStart
o boxPackEnd
, GTK sabe dónde quieres colocar
tus widgets por lo que puede cambiar automáticamente el tamaño y otras cosas interesantes.
boxPackStart :: (WidgetClass child, BoxClass self) => self -> child -> Packing -> Int -> IO ()
boxPackEnd :: (WidgetClass child, BoxClass self) => self -> child -> Packing -> Int -> IO ()
El parámetro de Packing
(empaquetado) especifica el modo en que los
widgets del contenedor se comportan cuando la ventana cambia de tamaño. PackNatural
indica que los widgets mantendrán su tamaño y posición, PackGrow
que su tamaño será adaptado, y con PackRepel
los widgets serán
espaciados entre ambos lados (manteniendo el tamaño). El último parámetro es un
Int
, que especifica el espaciado que se dejará entre este "hijo" y sus
vecinos.
El empaquetado sólo se aplica a la dimensión principal de la caja (horizontal o vertical).
Si, por ejemplo, indicas PackNatural
en vez de PackGrow
en el ejemplo anterior, el cambio de tamaño horizontal mantendrá los botones
en su tamaño original, pero los cambios verticales sí le harán cambiar de tamaño.
Esto se debe a que los botones se colocan homogéneamente en la caja horizontal.
(El primer parámetro es True) y la caja se adapta a los cambios de la ventana.
El próximo ejemplo clarificará más las cosas.