Getting Started

The first thing to do, of course, is download Gtk2Hs and install it. You can always get the latest version from http://haskell.org/gtk2hs/ and several Linux versions have their own Gtk2Hs packages. For Windows there is an installer available.

The next thing is to open the Gtk2Hs API reference documentation for your version. You will need to use this extensively to be able to find the names for widgets, methods, attributes and signals you might want to use. The contents lists all modules and there is also an index. Inside each module description there is also a class hierarchy. If a method, attribute or signal you expect is missing, it might belong to one of the superclasses of which your widget type is an instance.

To begin our introduction to Gtk2Hs, we'll start with the simplest program possible. This program will create a 200x200 pixel window and has no way of exiting except to be killed by using the shell.

GtkChap3a

import Graphics.UI.Gtk

main :: IO ()
main = do
  initGUI
  window <- windowNew
  widgetShowAll window
  mainGUI

You can compile the above program with the Glasgow Haskell Compiler (GHC) using:

ghc --make GtkChap3a.hs -o Chap3a

assuming GtkChap3a.hs is the filename. Alternatively you can use the interactive GHCi, for earlier and later versions of Gtk2Hs. (Because of threading problems intermediate versions will not work interactively. Gtk2Hs does not work with Hugs.)

The first line of the program imports the Gtk2Hs graphics library.

All Gtk2Hs programs run in main. The first line of that function's do block:

  initGUI

is a function called in all Gtk2Hs applications.

The next two lines in the block create and display a window and its contents:

  window <- windowNew
  widgetShowAll window

Rather than create a window of 0x0 size, a window without children is set to 200x200 by default so you can still manipulate it. Widgets that can be visible (not all can) may be shown or hidden using their own methods, but the second line works on a widget (here the window) and all its children.

The last line of main enters the Gtk2Hs main processing loop:

  mainGUI

and is another call you will see in every Gtk2Hs application. When control reaches this point, Gtk2Hs will sleep waiting for X events (such as button or key presses), timeouts, or file IO notifications to occur. In our simple example, however, events are ignored.

"Hello World" in Gtk2Hs

Now for a program with a widget (a button): the classic "hello world" à la Gtk2Hs.

GtkChap3b

If the button is clicked it will display the text "Hello World". This is implemented in the Haskell function hello with a button b as its argument. The type declaration actually states the type variable o is an instance of class ButtonClass. Gtk2Hs extensively uses Haskell classes to map the object hierarchy of the original GTK widgets. Each widget in Gtk2Hs, of course, has a Haskell type.

Widgets, and the classes their types belong to, usually have attributes. These can be set either by named methods or by the general set function, which uses a list-like notation as shown below. Of special interest here is the containerChild attribute of the window (actually of a superclass of the window) which states the relationship with the button. Because of this relationship widgetShowAll window will also make the button visible.

Widgets are connected to other widgets in a graphical dependency tree (not to be confused with the class hierarchy). Gtk2Hs also works with the Glade visual interface designer and, if you use Glade, such connections are visible in the Inspector pane. There is a separate introductory tutorial on how to use Glade with 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 is event driven. The mainGUI function will sleep until something happens, like a mouse being clicked, a window being destroyed or something else typical for a widget. Such events then trigger signals which in turn trigger user-defined functions to be evaluated. In this case the onClicked signal, emitted by the user clicking the button, is linked to the text being displayed on the same button. When the user destroys the window, unlike with the first program, main now exits cleanly.