[Tutorial-Port-Spanish Chapters 1,2,3 and index hthiel.char@zonnet.nl**20071208154317] addfile ./docs/tutorial/Tutorial_Port/es-chap1.xhtml hunk ./docs/tutorial/Tutorial_Port/es-chap1.xhtml 1 - + + + + + + Gtk2Hs Tutorial: Introducción + + + + + + + +

1. Introducción

+

Del sitio web de Gtk2Hs: Gtk2Hs es una libreria GUI (Interfaz gráfico de usuario) para Haskell basada en +Gtk+. Gtk+ es un conjunto de herramientas extensivo y maduro, multi-plataforma para crear interfaces gráficos de usuario.

+

El objetivo de este tutorial es el programador intermedio de Haskell, y cubre todo lo necesario para escribir los interfaces de usuario más +comunes. En particular los contenidos están indicados en el índice de este tutorial. Para los usuarios avanzados la +documentación de la API de Gtk2Hs contiene mucha más información.

+

Gtk+ es fundamentalmente una biblioteca de componentes llamados 'widgets', +que se organizan en una jerarquía orientada a objetos. En Gtk2Hs esto +se hace dando a cada widget tanto un tipo como una clase de tipo (type y type +class) de Haskell. De este modo el sistema de tipos de Haskell está rigurosamente +preservado, y el programador tiene todas las ventajas de la comprobación +de tipos del compilador y del interprete de Haskell de Glasgow (ghc). +Gtk2Hs tiene también muchas funciones para el casting de tipos.

+

Los widgets tienen atributos que controlan su comportamiento y apariencia, +existiendo dos funciones generales para obtener y establecer los atributos +de los mismos.

+

Para dar/establecer (set) uno o más atributos a un widget usa:

+
set widget [widgetAttr1 := foo, widgetAttr2 := fie, widgetAttr3 := bar]
+

Para obtener el valor de un atributo (get) de un widget usa:

+
x <- get widget widgetAttr1
+

Casi siempre hay funciones específicas para obtener y establecer +los atributos de los widgets, pero en el futuro serán eliminadas. +Actualmente, sin embargo es más común el uso de dichas funciones.

+

Todo lo que sucede en una aplicación en Gtk2Hs está determinado +por las acciones del usuario, como pulsaciones de ratón, presionado de +botones, selección de botones de radio y demás.A esto se le llama eventos y resultan en señales emitidas. +La información sobre los eventos, por ejemplo cuando el usuario pulsa el +botón derecho o izquierdo del ratón, se captura en campos de +datos que pueden ser consultados por el programador de Gtk2Hs. +Normalmente las señales se gestionan por funciones específicas de cada +tipo de widget. Se listan en la sección señales (*Signals*) de +la documentación de la API de ese widget. La mayoría toman una función +de tipo IO () como parámetro, pero algunas tienen algún resultado. +El programador de Gtk2Hs, por supuesto, debe escribir esas funciones que determinan la +respuesta del sistema a la acción del usuario.

+

Finalmente, el etablecimiento del árbol de widgets para tu aplicación y +la determinación de la disposición (layout) visual (empaquetado) puede +hacerse con el diseñador de interfaces de Glade. +Gtk2Hs se integra perfectamente con Glade y hay un tutorial introductorio +en el sitio web de Gtk2Hs. +Se recomienda el uso de Glade para el seguimiento de este tutorial.

+ + + addfile ./docs/tutorial/Tutorial_Port/es-chap2.xhtml hunk ./docs/tutorial/Tutorial_Port/es-chap2.xhtml 1 - + + + + + + Gtk2Hs Tutorial: Empezando + + + + + + +

2. Empezando

+ +

+Lo primero es bajarse el Gtk2Hs e instalarlo. Siempre se puede conseguir la última +versión de http://haskell.org/gtk2hs/ y +diversas versiones de Linux disponen de sus propios paquetes de Gtk2Hs. Hay un instalador +disponible para Windows. +

+ +

+Lo siguiente es abrir la documentación de referencia de la API para tu versión. +La vas a usar a menudo para encontrar los nombres de los widgets, los métodos, +atributos y señales que podrías querer usar. +Se listan todos los módulos y además se dispone de un índice. +Dentro de cada descripción de módulo se muestra la jerarquía de clases. +Si un método, atributo o señal que esperas encontrar no aparece, podría +pertenecer a una de las superclases de las que tu tipo de widget es una instancia. +

+ +

+Nuestra introducción a Gtk2Hs, empieza con el programa más simple posible. +Este programa crea una ventana de 200x200 pixeles y no hay modo de salir de ella, +exceptuando que sea "matada" usando la shell.

+ +

Window

+ +
import Graphics.UI.Gtk
+
+main :: IO ()
+main = do
+  initGUI
+  window <- windowNew
+  widgetShowAll window
+  mainGUI
+
+ +

+Puedes compilar el programa que aparece arriba con el compilador de Haskell +de Glasgow (Glasgow Haskell Compiler) GHC usando: +

+ +
ghc --make GtkChap2.hs -o Chap2
+
+ +

+asumiendo que GtkChap2.hs es el nombre del fichero. También puedes usar +el intérprete interactivo GHCi para probarlo, para versiones anteriores y posteriores +de Gtk2Hs. Debido a problemas con los hilos (threads) las versiones intermedias no funcionarán +interactivamente. (Gtk2Hs no funciona con Hugs.) +

+ +

+La primera línea del programa importa la librería gráfica de Gtk2Hs. +

+ +

+Todos los programas de Gtk2Hs se ejecutan en main. La primera línea de +la función es un bloque do: +

+ +
  initGUI
+
+ +

+es una función usada en todas las aplicaciones de Gtk2Hs. +

+ +

+Las siguientes dos líneas del bloque crean y muestran una ventana y sus contenidos: +

+ +
  window <- windowNew
+  widgetShowAll window
+
+ +

+En vez de crear una ventana de tamaño 0x0, una ventana sin hijos se crea por defecto de +200x200 puntos, de modo que pueda ser manipulada por el usuario. Los Widgets que se pueden +visualizar (no todos pueden visualizarse) deben ser mostrados u ocultados usando sus propios +métodos, pero la segunda línea funciona en el widget (aquí la ventana) y todos sus hijos. +

+ +

+La última línea de main activa el bucle principal de proceso de Gtk2Hs: +

+ +
  mainGUI
+
+ +

+que es otra llamada que verás en todas las aplicaciones Gtk2Hs. Cuando el +control alcanza este punto, Gtk2Hs dormirá esperando algún evento (pulsado +de un botón o de una tecla), timeouts, o notificaciones en los ficheros de entrada/salida. +En nuestro ejemplo anterior, sin embargo, los eventos son ignorados. +

+ +

"Hello World" en Gtk2Hs

+ +

+Vamos ahora por un programa con un widget (un botón): El clásico "hello world" 'a +la Gtk2Hs'. +

+ +

Hello World application

+ +

+Si se pulsa el botón, mostrará el texto "Hello World". Esto está implementado +en la función Haskell hello con un botón b como argumento. +La declaración de tipos establece la variable o como una instancia de la clase +ButtonClass. Gtk2Hs usa extensivamente las clases de Haskell para reflejar la +jerarquía de objetos de los widgets GTK originales. Cada widget en Gtk2Hs tiene, por +supuesto, un tipo de Haskell. +

+

+Los widgets, y las clases a las que sus tipos pertenecen, normalmente tienen atributos. +Estos pueden establecerse, por métodos específicos o por la función +general set, que usa una notación tipo lista como se muestra a continuación. +De especial interés es el atributo containerChild de la ventana (de una superclase +de la ventana) que indica la relación con el botón. Debido a que existe esta relación +widgetShowAll window hará el botón visible. +

+

+Los widgets están conectados a otros widgets en un árbol de dependencia gráfica +(no debería confundirse con la jerarquía de clases). Gtk2Hs también trabaja con el +diseñador de interfaz visual de Glade y, si usas Glade, estas relaciones serían visibles +en el panel del Inspector. +Hay un tutorial independiente sobre como usar +Glade con Gtk2Hs.

+ +
import Graphics.UI.Gtk
+
+hello :: (ButtonClass o) => o -> IO ()
+hello b = set b [buttonLabel := "Hello World"]
+
+main :: IO ()
+main = do
+  initGUI
+  window <- windowNew
+  button <- buttonNew
+  set window [windowDefaultWidth := 200, windowDefaultHeight := 200,
+              containerChild := button, containerBorderWidth := 10]
+  onClicked button (hello button)
+  onDestroy window mainQuit
+  widgetShowAll window
+  mainGUI
+
+ +

+Gtk2Hs está guiado por los sucesos (event driven). La función +mainGUI dormirá hasta que algo suceda, como que el ratón +sea pulsado, una ventana sea destruida o alguna otra cosa típica de un widget. +Los sucesos entonces activan señales que a su vez activan las funciones que ha +definido el usuario para ser evaluadas si se da esa circunstancia. +En este caso la señal onClicked, emitida por el usuario al pulsar el botón, +se engancha al texto que será mostrado en ese mismo botón. +Al destruir la ventana, no como en el primer programa, main ahora sale limpiamente. +

+ + + + addfile ./docs/tutorial/Tutorial_Port/es-chap3-1.xhtml hunk ./docs/tutorial/Tutorial_Port/es-chap3-1.xhtml 1 - + + + + + + Gtk2Hs Tutorial: Empaquetando Widgets + + + + + + + +

3.1 Empaquetando Widgets

+ +

+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.

+ +

Teoría de las cajas de 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. +

+ +

Packed buttons

+ +
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. +

+ + + + addfile ./docs/tutorial/Tutorial_Port/es-chap3-2.xhtml hunk ./docs/tutorial/Tutorial_Port/es-chap3-2.xhtml 1 - + + + + + + Gtk2Hs Tutorial: Programa de demostración del empaquetado + + + + + + + +

3.2 Programa de demostración del empaquetado

+ +

+En este ejemplo, la base de todos los widgets es una caja vertical, que a su vez es hija +de la ventana. Los widgets hijos no se muestran de modo homogéneo y no hay un espacio adicional +(diferente del espaciado estándar). +Hay seis cajas horizontales en la caja vertical, tal y como se definen con la función + makeBox, que tiene el tipo mostrado. Además, hay dos etiquetas en la caja vertical +así como dos separadores horizontales. El último widget es el botón Quit +cuya señal onClicked se engancha a la función mainQuit. +

+ +

+Los separadores se crean con hSeparatorNew y están espaciados por boxPackStart +con un espacio de separación de diez píxeles. Las etiquetas (label) se crean con labelNew +con un Maybe String y su posición se establece con miscSetAlignment para estar +justificados a la izquierda y arriba. +

+ +

Packing demo application

+ +

+La función makeBox :: Bool -> Int -> Packing -> Int -> IO +HBox demuestra como los widgets de Gtk2Hs encajan dentro del sistyema de tipos de haskell. +Packing es simplemente un tipo, como Int y Bool +y IO HBox es como IO String en el típico IO. +La función crea cinco botones, los etiqueta con el texto apropiado y los empaqueta en una +caja horizontal. Entonces la función se emplea en el programa principal para crear los modos de +empaquetado deseados.

+ +
import Graphics.UI.Gtk
+
+main :: IO ()
+main = do
+  initGUI
+  window     <- windowNew
+  vbox       <- vBoxNew False 0
+  set window [containerBorderWidth := 10,
+              windowTitle := "Packing Demonstration",
+              containerChild := vbox]
+  label1     <- labelNew (Just "hBoxNew False 0")
+  miscSetAlignment label1 0 0
+  boxPackStart vbox label1 PackNatural 0
+  box1       <- makeBox False 0 PackNatural 0
+  boxPackStart vbox box1 PackNatural 0
+  box2       <- makeBox False 0 PackRepel 0
+  boxPackStart vbox box2 PackNatural 0
+  box3       <- makeBox False 0 PackGrow 0
+  boxPackStart vbox box3 PackNatural 0
+  sep1       <- hSeparatorNew
+  boxPackStart vbox sep1 PackNatural 10
+  label2     <- labelNew (Just "hBoxNew True 0")
+  miscSetAlignment label2 0 0
+  boxPackStart vbox label2 PackNatural 0
+  box4       <- makeBox True 0 PackNatural 0
+  boxPackStart vbox box4 PackNatural 0
+  box5       <- makeBox True 0 PackRepel 0
+  boxPackStart vbox box5 PackNatural 0
+  box6       <- makeBox False 0 PackGrow 0
+  boxPackStart vbox box6 PackNatural 0
+  sep        <- hSeparatorNew
+  boxPackStart vbox sep PackNatural 10
+  quitbox    <- hBoxNew False 0
+  boxPackStart vbox quitbox PackNatural 0
+  quitbutton <- buttonNewWithLabel "Quit"
+  boxPackStart quitbox quitbutton PackRepel 0
+  onClicked quitbutton mainQuit
+  onDestroy window mainQuit
+  widgetShowAll window
+  mainGUI
+
+
+makeBox :: Bool -> Int -> Packing -> Int -> IO HBox
+makeBox homogeneous spacing packing padding = do
+  box     <- hBoxNew homogeneous spacing
+  button1 <- buttonNewWithLabel "boxPackStart"
+  boxPackStart box button1 packing padding
+  button2 <- buttonNewWithLabel "box"
+  boxPackStart box button2 packing padding
+  button3 <- buttonNewWithLabel "button"
+  boxPackStart box button3 packing padding
+  button4 <- case packing of
+                  PackNatural -> buttonNewWithLabel "PackNatural"
+                  PackRepel   -> buttonNewWithLabel "PackRepel"
+                  PackGrow    -> buttonNewWithLabel "PackGrow"
+  boxPackStart box button4 packing padding
+  button5 <- buttonNewWithLabel (show padding)
+  boxPackStart box button5 packing padding
+  return box
+
+ +

+La imagen de abajo muestra los efectos de modificar el tamaño de la ventana horizontalmente. +En el primer grupo, con homogeneous en False, las modificaciones +horizontales dejan la frimera fila de botones como estaban, espacian la segunda fila de modo equilibrado +y agrandan los botones de la tercera fila. En el segundo grupo, los botones se empaquetan homogeneamente, y +las primeras dos filas se verán iguales. Si modificamos el tamaño verticalmente, simplemente añadirá +espacios adicionales al final, ya que la caja vertical ha sido inicializada con False. +

+ +

Resized packing demo application

+ + + + + addfile ./docs/tutorial/Tutorial_Port/es-chap3-3.xhtml hunk ./docs/tutorial/Tutorial_Port/es-chap3-3.xhtml 1 - + + + + + + Gtk2Hs Tutorial: Empaquetar mediante tablas + + + + + + +

3.3 Empaquetar mediante tablas

+ +

+Vamos a aprender otro modo de empaquetar: las tablas. Pueden ser extremadamente +útiles en determinadas situaciones. Usando tablas, creamos una cuadrícula (grid) en la que podemos situar +los widgets. Los widgets pueden ocupar tantos espacios como especifiquemos. +

+ +

+En primer lugar consideraremos la función tableNew (Nueva tabla)): +

+ +
tableNew :: Int -> Int -> Bool -> IO Table
+
+ +

+El primer argumento es el número de filas que tendrá la tabla, y el segundo, +el número de columnas. +

+ +

+El argumento booleano (homogéneo) indica como se establece el tamaño +de las cajas de la tabla. Si homogéneo se establece a True, +entonces las cajas se crean al tamaño del mayor widget de la tabla, y todas iguales. Si +homogéneo se establece a False, el tamaño de las cajas de la tabla +está determinado por el widget más alto de su fila, and el widget más ancho de su columna. +Por ejemplo, supón que tienes una matríz de 10x10 botones cada uno etiquetado con los numeros +del 1 al 100. Así, te aparecen tres posibles anchuras, la de los números del 1 al 9, +la de los números del 10 al 99 y la del 100. Si has establecido en True el valor de +homogéneo, todos los botones serán iguales y el ancho corresponderá al del botón 100. +Sin embargo, si el valor que has puesto es Falso, la última columna mantendrá el ancho del botón de 100 +y las otras el de los botones correspondientes al 10 al 99. En este ejemplo las alturas de los botones +serían iguales con las dos opciones, ya que sólo tenemos una posible altura. +

+ +

+Las filas y colunas se numeran desde 0 hasta n, donde +n es el número especificado en la llamada a tableNew. Así +si especificas filas = 2 y columnas = +2, la distribución parecerá algo así: +

+ +
 0          1          2
+0+----------+----------+
+ |          |          |
+1+----------+----------+
+ |          |          |
+2+----------+----------+
+
+ +

+Fíjate en que el sistema de coordenadas empieza en la esquina superior +izquierda. Para colocar un widget en una caja, usa la siguiente función: +

+ +
tableAttach :: (TableClass self, WidgetClass child)
+  => self            -- self         - La tabla.
+  -> child           -- child        - El widget a añadir.
+  -> Int             -- leftAttach   - El número de la columna para situar el lado izquierdo 
+                     --                del widget a colocar.
+  -> Int             -- rightAttach  - El número de la columna para situar el lado derecho
+                     --                del widget a colocar.
+  -> Int             -- topAttach    - El número de la fila donde situar la parte superior del
+                     --                widget a colocar.
+  -> Int             -- bottomAttach - El número de la fila donde situar la parte inferior del
+                     --                widget a colocar.
+  -> [AttachOptions] -- xoptions     - Se emplea para indicar las propiedades del widget hijo
+                     --                cuando la tabla modifica su tamaño (horizontales)
+  -> [AttachOptions] -- yoptions     - Igual que xoptions, exceptuando que el campo determina
+                     --                el comportamiento vertical
+  -> Int             -- xpadding     - Un valor entero que especifica el espacio en blanco a
+                     --                izquierda y derecha de la tabla del widget que se añade.
+  -> Int             -- ypadding     - El espacio arriba y abajo del widget.
+  -> IO ()
+
+ +

+El primer argumento, (self), es la tabla que has creado y el segundo, +(child), es el widget que quieres colocar en la tabla. +

+ +

+Los argumentos izquierdo y derecho (leftAttach, rightAttach) indican donde debe ponerse +el widget, y cuantas cajas usar. Si quieres poner un botón en la parte de abajo a la derecha +de tu tabla de 2x2, y quieres colocar solo esa entrada, +leftAttach debería ser = 1, rightAttach = +2, topAttach = 1, y bottomAttach += 2. +

+ +

+Ahora, si quieres que un widget llene completamenta la fila superior +de nuestra tabla de 2x2, deberías susar los siguientes valores: +leftAttach = 0, rightAttach = +2, topAttach = 0, and bottomAttach = +1. +

+ +

+xoptions y yoptions se usan para indicar las opciones de empaquetado y +la lista puede contener más de una para permitir múltiples opciones. +

+ +

Las posibles opciones son:

+ +
+
Fill
+
+ Si la caja de la tabla es mayor que el widget, y se especifica Fill, + el widget se expandirá hasta ocupar todo el espacio disponible. (como un gas cualquiera). +
+ +
Shrink
+
+ Si el widget de la tabla tiene disponible menos espacio del que necesita (normalmente + porque el usuario ha cambiado el tamaño de la tabla), los widgets deberían ser empujados + de la parte inferior de la tabla y desaparecerían. Si se especifica Shrink + los widgets de reducirán con la tabla. +
+ +
Expand
+
+ Esto originará que la tabla se expanda hasta usar todo el espacio disponible en la + ventana. +
+
+ +

+ El padding funciona como en las cajas, dejando un área libre alrededor + del widget, del tamaño especificado en píxeles +

+ +

+tableAttach tiene muchas opciones, así que ponemos un resumen: +

+ +
tableAttachDefaults :: (TableClass self, WidgetClass widget)
+  => self   -- self         - La tabla.
+  -> widget -- widget       - El widget a añadir.
+  -> Int    -- leftAttach   - El número de la columna en el que se situará el lado
+            --                izquierdo del widget a añadir.
+  -> Int    -- rightAttach  - El número de la columna en el que se situará el lado
+            --                derecho del widget a añadir.
+  -> Int    -- topAttach    - El número de la fila en el que se situará el lado superior
+            --                del widget.
+  -> Int    -- bottomAttach - El número de la fila en el que se situará el lado inferior
+            --                del widget.
+  -> IO ()
+
+ +

+Los valores usados para los parámetros de [AttachOptions] son +[Expand, Fill], y el espacio (padding) se fija en 0. El resto de los +argumentos son los mismos que para la función previa. +

+ +

+También tenemos tableSetRowSpacing y +tableSetColSpacing. Estas funciones colocan espacios en la fila (row) o columna (col) indicada. +

+ +
tableSetRowSpacing :: TableClass self=> self-> Int -> Int -> IO ()
+
+ +
tableSetColSpacing :: TableClass self => self -> Int -> Int -> IO ()
+
+ +

+El primer argumento Int es la fila/columna y el segundo es el espacio +en píxeles. Fíjate que en el caso de las columnas, el espacio se situa a la derecha de +la columna y en las filas, bajo la fila. +

+ +

+Puedes fijar un espacio fijo para todas las filas y/o las columnas con: +

+ +
tableSetRowSpacings :: TableClass self=> self-> Int -> IO ()
+
+ +

y:

+ +
tableSetColSpacings :: TableClass self => self -> Int -> IO ()
+
+ +

+Fíjate que con estas llamadas, la última fila y la última columna no +consiguien ningún espacio. +

+ +

Ejemplo de empaquetado con tabla

+ +

+Vamos a hacer una ventana con tres botones en una tabla 2x2. Los primeros dos botones +se colocarán en la fila de arriba. Un tercer botón (Quit) se colocará en la fila +de abajo, ocupando ambas columnas. Quedará así: +

+ +

Table packing

+ +

Aquí está el código fuente:

+ +
import Graphics.UI.Gtk
+
+main :: IO ()
+main = do
+  initGUI
+  window  <- windowNew
+  set window [windowTitle := "Table", containerBorderWidth := 20,
+              windowDefaultWidth := 150, windowDefaultHeight := 100]
+  table   <- tableNew 2 2 True
+  containerAdd window table
+  button1 <- buttonNewWithLabel "On"
+  onClicked button1 (buttonSwitch button1)
+  tableAttachDefaults table button1 0 1 0 1
+  button2 <- buttonNewWithLabel "Off"
+  onClicked button2 (buttonSwitch button2)
+  tableAttachDefaults table button2 1 2 0 1
+  button3 <- buttonNewWithLabel "Quit"
+  onClicked button3 mainQuit
+  tableAttachDefaults table button3 0 2 1 2
+  onDestroy window mainQuit
+  widgetShowAll window
+  mainGUI
+
+buttonSwitch :: Button -> IO ()
+buttonSwitch b = do
+  txt <- buttonGetLabel b
+  let newtxt = case txt of
+                 "Off" -> "On"
+                 "On"  -> "Off"
+  buttonSetLabel b newtxt
+
+ +

+La función buttonSwitch es asocia a ambos botones de la fila superior. +La función buttonGetLabel es un ejemplo de cómo conseguir un atributo +de un widget usando un método estándar. Hay una alternativa más general get +(análoga a set) que toma un widget y un atributo. +En el ejemplo anterior sería: +

+ +
  txt <- get b buttonLabel
+
+ +

+con el mismo resultado. +

+ + + + + addfile ./docs/tutorial/Tutorial_Port/es-index.xhtml hunk ./docs/tutorial/Tutorial_Port/es-index.xhtml 1 - + + + + + + Gtk2Hs Tutorial + + + +
+

Tutorial de Gtk2Hs

+
+
+

Hans van Thiel

+
+
+

Una Adaptación del Tutorial de GTK+ 2.0 por

+

Tony Gale

+

Ian Main

+

&

+

The GTK Team

+
+
+

Indice

+
    +
  1. + 1. Introducción +
  2. +
  3. + 2. Empezando +
  4. +
  5. 3. Empaquetado +
      +
    1. + 3.1 Empaquetando Widgets +
    2. +
    3. + 3.2 Programa de demostración de empaquetado +
    4. +
    5. + 3.3 Empaquetado usando tablas +
    6. +
  6. + +
+
+

Copyright del tutorial y nota sobre los permisos

+

El Tutorial GTK tiene el Copyright © 1997 Ian Main.

+

Copyright © 1998-2002 Tony Gale.

+

Copyright © 2007 Hans van Thiel and Alex Tarkovsky.

+

Copyright © 2007 Traducción española Laszlo Keuschnig

+

Se permite hacer y distribuir copias exactas de este manual + siempre que la información del copyright y esta nota + sobre los permisos se mantenga en todas las copias.

+

Se permite copiar y distribuir versiones modificadas de este + documento bajo las condiciones de copia exacta, siempre que esta + información sobre el copyright se incluya exactamente como + en el original, y que el trabajo completo derivado de este se + distribuya bajo las condiciones de una nota de permisos idéntica + a esta.

+

Se permite copiar y distribuir traducciones de este documento + en otras lenguas bajo las condiciones expresadas para las versiones + modificadas.

+

Si pretende incorporar este documento a un trabajo impreso, por + favor contacte con el responsable del mantenimiento del mismo, y + haremos un esfuerzo para asegiurarle que dispone de la informació + más actualizada disponible.

+

No hay garantíde que este documento responda a sus + propósitos. Se proporciona como un recurso libre y gratuito. + Por tanto, los autores y los responsables del mantenimiento de + la información no pueden dar ninguna garantía de que + la información sea correcta.

+

Otros reconocimientos

+

Hemos usado y agradecemos su uso 'Programming with gtkmm' de Murray Cumming et al. + y el tutorial del Inti (Integrated Foundation Classes) tutorial del Inti team.

+

El Capítulo 7 está basado principalmente en el Capítulo 11 de 'Programming with gktmm' y la demo + incluída en la distribución de Gtk2Hs.

+ + +