Handling Events
Handling events in FLTK is done via callbacks. Unlike other alternatives, probably more suitable for C++ object oriented approach, like signals and slots, implemented in Qt, FLTK callback mechanism is fairly simple, but no less powerfull.
FLTK callbacks are one of the reasons why FLTK is so fast and has small core so edelib explores this property extensively. For example, when you receive a D-BUS message via EdbusConnection, it will be reported via callback. The same applies when something was changed in directory, monitored with DirWatch.
Example Application
To demonstrate FLTK callbacks, here will be presented a simple application with Close
button, where pressing the button will close the window. Application will use Window
class from edelib.
/* event.cpp */ #include <FL/FL.H> #include <FL/Fl_Button.H> #include <edelib/Window.h> EDELIB_NS_USING_AS(Window, MainWindow) /* called when button is pressed */ static void close_cb(Fl_Widget*, void *w) { MainWindow *win = (MainWindow*)w; win->hide(); } int main(int argc, char **argv) { MainWindow *win = new MainWindow(115, 60, "Demo"); Fl_Button *button = new Fl_Button(15, 15, 90, 25, "&Close"); /* register our callback */ button->callback(close_cb, win); win->end(); w->show(argc, argv); return Fl::run(); }
As you can see, callback()
function, besides a pointer to function, accepts additional parameter called user data
; in this case is our window object, so we can call it's memeber hide()
that will close the window.
FLTK uses callbacks in many places; you can get events when window is closed, when text is modified, etc. Designing a Simple Text Editor chapter in FLTK documentation gives some example how to monitor changes when text is changed in editor widget.
More from callbacks
Sometimes you want to send more data to callback, other than single object. For example, callback function needs to access object who owns callbacks with additional data; you can use struct or class to pack them, but FLTK already solves named problem.
If you look carefully at above example, 'callback()
' receives two parameters: some Fl_Widget*
and void*
; void*
is used to send win object, but Fl_Widget*
can be used to (implicitly) send button object. Here is how it works:
/* event.cpp */ ... /* called when button is pressed */ static void close_cb(Fl_Button *button, void *w) { /* we can access button object too */ } int main(int argc, char **argv) { ... /* register our callback */ button->callback((Fl_Callback*)close_cb, win); ... }
The main difference from original example is how we explicitly cast-ed callback function to 'Fl_Callback*
' and our callback function close_cb
is now able to accept any Fl_Widget inherited object. If you try without that, the compiler will complain.