WxHaskell

From HaskellWiki
Revision as of 15:33, 20 February 2007 by EndreyMark (talk | contribs) (Merge in a single item the pdf and ppt versions of slides Koen Lindström Claessen: Graphical User Interfaces in Haskell)
Jump to navigation Jump to search

What is it?

wxHaskell is a Haskell binding to wxWidgets (formerly known as wxWindows), which allows you to create graphical user interfaces using native widgets on Windows, Mac and *nix (gtk).

Homepage

http://wxhaskell.sourceforge.net/

Installation

Sadly, wxHaskell development is not as active as it could be (at time of writing - Aug 2006), which makes compilation and installation of recent versions of wxHaskell more of trial than it needs to be.

The wxHaskell install page contains details of different people's experience in compiling and installing wxHaskell against various versions of wxWidgets on various platforms.

Tips

  1. Getting Started:
  2. Text:
    • retrieving the text of a TextCtrl: mytext <- get mytextEntry text
    • staticText misbehaves on resize: make sure that you are giving the widget enough space... for example, if you want a one-line staticText, you should
      • use hfill on the staticText
      • not use hfill (or hfloat...) or any other widgets in the same row
  3. Layout:
    • Don't bother looking at the the examples yet, the API is better for this
    • See the Haddock-generated documentation for Graphics.UI.WX.Layout
    • Got layout troubles? Packing things inside yet another panel seems to help sometimes
  4. Scroll Bars:
    • scrollbars are just windows. You create a scrollFrame, and any widgets you want inside the scrollbars, you make this scrollFrame their parent
    • see samples/wx/ImageViewer.hs
    • the following widgets (controls) already include scrollbars : listBox
  5. Mac OS X (Darwin)
    • for ghci usage download EnableGui.hs from wxhaskell.sourceforge.net/download/EnableGUI.hs and
      ghc -fffi -package wx EnableGUI.hs
      ghci -package wx HelloTest.hs EnableGui.hs
      -- followed by :m +EnableGUI and
      enableGUI >> main

A Short Guide

It is helpful to a get a grip on three basic concepts: Widgets, Layout and Events.

Widgets

Widgets are the basic components of any GUIs. They include buttons, radio boxes, frames and what not. There are essentially two kinds of widgets: windows and controls. Windows are widgets that contain other widgets. Note: what you might normally think of as a window, i.e. that big thing with the close, minimise, maximise buttons on your OS in wxHaskell is a special kind of window called a "frame".

We define windows by calling some function (for example, frame) with a list of attributes. Here is a example which creates a frame with the title bar "Hello!":

hello
  = do f    <- frame    [text := "Hello!"]

The more interesting widgets are controls such a buttons and check boxes. We define controls almost the same way as windows, by calling some function (for example, button) with a window and a list of attributes:

hello
  = do f    <- frame    [text := "Hello!"]
       quit <- button f [text := "Quit"]

The relevant documentation:

 * http://wxhaskell.sourceforge.net/doc/Graphics.UI.WX.Controls.html
 * http://wxhaskell.sourceforge.net/doc/Graphics.UI.WX.Window.html

Layout

Layout means telling wxHaskell how to arrange your widgets with respect to each other. It is something you would normally do after you have defined all your widgets.

We won't go into much detail here because the Haddock-generated documentation is very helpful here, but here is a trivial example of layout where all we do is stick the quit button in the frame. Notice how layout is just an attribute of the frame widget.

hello
  = do f    <- frame    [text := "Hello!"]
       quit <- button f [text := "Quit"]
       set f [layout := widget quit]
 * http://wxhaskell.sourceforge.net/doc/Graphics.UI.WX.Layout.html

Scrolled windows

Widgets (for example, listboxes) will automatically create scrolled windows for you. You only need to deal with them if you are working with bitmaps.


XRC

How do you use XRC-Files with wxHaskell? Is it possible?

- I also very much would like to know this. Anyone?

There isn't a way, but it sounds like it might be a fun library to build

Events

Events are what joins your widgets to the rest of your code. Whenever a user manipulates a widget (e.g. presses a button), an event is triggered. If you set the appropriate attributes, you can cause these events to call some piece of Haskell code. In the following example, we set the "on command" attribute to close the frame f.

hello
  = do f    <- frame    [text := "Hello!"]
       quit <- button f [text := "Quit", on command := close f]
       set f [layout := widget quit]
* http://wxhaskell.sourceforge.net/doc/Graphics.UI.WX.Events.html

Idle Event

Use idle event for automation.

Tricky problems and their solutions

Long computations

Scenario: you've got a looooooong computation and you want to update a progress bar or you want to have a 'STOP' button which aborts the computation

Solution:

  • wxcApp(Safe)Yield

FIXME: elaborate on this!

Managing multiple windows

Scenario: you have a main window MAIN with some information. You want to create a secondary window PARAMS in which the user edits some configuration stuff. When the user closes PARAMS, the window MAIN should be updated to reflect the new settings.

You have some code which looks like

set paramsButton [ on command := do createParamsWindow
                                    updateMainWindow ]

Problem: MAIN is not updated... at least, not until you call PARAMS a second time.

Observations:

  • This is NOT a problem with Haskell laziness

Explanation: updateMainWindow tries to read the new configuration value, but it does not succeed, because no configuration values have changed. Why not? Simpler than it looks: all the createParamsWindow function does is creates a window with some widgets, assign some commands to said widgets, and return. There's nothing in the createParamsWindow code that says the function should only return when PARAMS has been closed.

Solution: Pass createParamsWindow a function which updates the MAIN window:

set paramsButton [ on command := do createParamsWindow updateMainWindow ]

When the user closes PARAMS, one of the final things it should do is call this update function

External links

See also