Introduction to programming in Fltk

All public symbols in fltk start with the characters 'F' and 'L':

I intend someday to put all the public symbols of fltk in to a C++ namespace "Fl::". Currently many compilers do not support namespaces. I simulate a portion of the namespace with a dummy "class Fl" but most symbols are not in it because they would all have to be in the same header file. The change to namespaces will be incompatable and will require replacing all occurances of fl_ or Fl_ with Fl::

The first thing your program should do is construct one or more trees of Fl_Widgets. The base widget of each of these is an Fl_Window widget. The constructors for widgets automatically add them as children of the most recent created window widget (use window->end() to stop this). Constructing the widgets does not require the display to be open and does not open it, unless you purposely open it to get information such as the width of a font.

Fl_Windows are displayed on the screen with Fl_Window::show(). For the first window you may also use Fl_Window::show(argc,argv) and fltk will automatically parse some startup arguments such as -display.

Then the program repeatedly calls Fl::wait(). Each time "something happens" Fl::wait() returns, usually after a block of X events have been read and processed. It is often useful for a program to check global state after each event, and fltk makes this easy by leaving the main loop under your control.

Each widget has a single "callback". This is a function that is called when something happens (such as the user pressing a button). Fltk avoids all the complexities of signals/slots by having only a single callback. Instead a when() method on the object selects when the callback is done (ie. when a slider is moved or when the mouse is released).

The callback is passed a pointer to the widget and a void* user_data field. This is redundant, as the user_data can be determined from the widget, but was done for XForms compatability and to make the same callbacks useful for menu items. Typically you want to turn the callback into a method on some C++ object. A simple way is to use the user_data as a pointer to the object. A more common but harder to understand way is to store the object in the parent widget's user_data field, since usually all the controls on a window are for the same object, this lets you use the user_data for an abitrary method argument.

To display graphic data, you must subclass either Fl_Window or Fl_Widget and define the virtual draw() method. This can use functions defined in <FL/fl_draw.H>, or can use system-specific calls such as Xlib. If the data being displayed changes, your main program calls the redraw() method on your widget, and fltk will call draw() while waiting for the next event. Subclassing Fl_Window or Fl_Widget is so easy that I felt it unnecessary to provide the "canvas" widget that most toolkits have.

If your program needs to monitor another device (such as stdin) you can provide a callback routine for when it becomes ready, by using Fl::add_fd(i). If your program needs something to happen at regular intervals you can define a timeout callback with Fl::add_timeout(time).

Building a large hierarchy is made much easier with fluid (the Fast Light User Interface Designer). This is a program that lets you interactively design the widget layout and set all the properties visually. It outputs C++ source code that you compile and link with your program. All you have to write is the main loop and any callbacks.

(back to contents)