By Michael Gleicher, September
11, 2005 Modified by Yu-Chi Lai at 2006
provided some tutorials for
getting started with FlTk.
These are very "example oriented" - they show you some FlTk example
programs, and expect you to learn from that. The purpose of this document is
to give you some insight onto how and why FlTk works,
and to give you some ideas on how to use FlTk.
You might want to look at the other tutorials first.
important resource for FlTk is
Note: you probably have access to a copy on your local disk as well.
Unfortunately, the tutorial chapter
starts with an example that is too easy, and quickly escalates to one that is
central concept in FlTk is
a widget. A widget
is an object that takes up a rectangular area on the screen, knows how to draw
itself, and knows how to respond to events. Widgets can contain other widgets.
almost everything is a widget. For example, a window is just a special kind of
important concept in FlTk is
an event. Programs
in FlTk are
event driven. That is, they generally sit around waiting for something (an
event) to happen. Examples of events are mouse clicks, mouse movements, the
mouse entering or exiting a widget, a window being shown, or any number of
other things. When an event happens, FlTk figures
out which widgets to tell about it.
a mechanism called a callback to
allow programmers to give behavior to pre-defined widgets. A callback is a
function that gets called at a certain time. For example, a push button widget
these built in) needs to know what to do when the user pushes the button. For
widgets that are defined by the application programmer (not built into FlTk),
the programmer must provide an event handling method for the widget -
callbacks are not used.
How does my program really work?
programs (like we will write for CS559)
usually have a structure like this:
- You create a number of windows (sometimes just 1) that have some number
of other widgets inside of them.
- You tell FlTk to
put these windows up on the screen (e.g. to be shown). Note that calling a
widget's show method does not actually draw the widget. It simply tells FlTk that
the widget should be visible, so that it will be drawn at an appropriate
time. Also note that a widget is not drawn unless its parent is also shown.
- You have a simple loop where your program waits for an event, and then
has FlTk pass
that event on to the appropriate widgets.
all of the real work of your program happens when the widgets respond to
other ways to organize FlTk programs.
For example, your program can do computations and periodically check to see if
there are events to respond to, and if so pass them to FlTk.
we strongly encourage you to program in the event driven style.
When and where do I get to draw?
Since this is a graphics class,
you might wonder when you actually get to do any drawing on the screen. The
short answer is that drawing happens inside of a widget's draw method when FlTk thinks
the widget needs to get redrawn.
The way that
most drawing happens in FlTk is
that you (the application programmer) defines a new type of widget that knows
how to do the drawing that you want to do. You do this by defining a new class
that is a subclass of some existing type of widget and overriding the draw
- Note: you
should never call
the draw method for any widget. FlTk calls
the draw method when it thinks the widget needs to be drawn. For example,
when the widget first appears on the screen, or if the widget's parent
window is uncovered. If you think that some widget needs to be redrawn, you
don't call its draw method - instead, you call its damage method which marks
the window so that FlTk will
call the draw method next time its appropriate.
a set of different functions that can go inside of a widget's draw method for
drawing things like lines, images, and text. For CS559,
we typically won't use these - instead relying on OpenGL to
be our drawing library. A special type of widget allows OpenGL function
calls to be placed into the draw method.
Some widgets, like windows, can
have other windows placed inside of them.
get placed inside of the "current container." Something becomes the "current
container" when it is created, or by using the begin method. So in the
Fl_Window* w1 = new Fl_Window(100,100,400,200,"Window 1");
Fl_Window* w2 = new Fl_Window(500,100,400,200,"Window 2");
Fl_Slider* sl = new Fl_Value_Slider(20, 270, 250, 25);
will appear in Window 2. It is good programming practice to call end when you
are done putting things inside of a container.
Making Things Happen
Making a window and putting a
widget (like a button or slider) in it should not be hard. The trick is giving
the widget the correct behavior when the button is pressed or the slider
changes value. The way that we do this is by attaching a callback function to
A callback is
a function that we attach to a widget. A widget callback function must take
two arguments. The first is a pointer to the widget, and the second is a
pointer whose value is stored inside the widget (called the user data).
are writing a callback for a slider. When the slider's value changes, you want
an object on the screen to change. You need some mechanism for the two to know
about each other. Here are some choices (there are many others):
- You can give your screen object a pointer to the slider. Every time the
object draws itself, it will ask the slider for its value. This style is
generally not recommended because it causes the program's main parts to
depend on its user interface.
- You can use a global variable to store a pointer to the object. That way
the callback function can access the global variable. Using lots of global
variables is not generally considered good programming style.
- You can store the pointer to the object as the slider's user data. One
problem with this is that you can only store one user data pointer per
- You can make a new type of widget that is a subclass of slider. This
widget will be a slider that stores extra information in it for use in its
Style #4 is
nice because it allows you to write your code in a more "object oriented
style" as follows
void myCallback(Fl_Widget* w, void * p)
class MySlider : public Fl_Value_Slider
MySlider(int x, int y, int w, int h, const char* label) :
Now, you can
add member variables to the MySlider class
so that the doCallback routine has as much data as it needs.
callback should cause something to happen on the screen, you will need to have
your widgets redraw. If you change the value of a built in widget, they will
do the right thing. However, if you change your data structures and expect
your widgets to notice, you have best tell them by calling their damage
Because FlTk callbacks
pass generic pointers (Fl_Widget* for the widget pointer, and a void* for the
user data), you will often need to use casts.