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.