Beginner questions.

48 views
Skip to first unread message

Jefferson Costa

unread,
May 3, 2023, 3:48:01 AM5/3/23
to fltk.general
Hi everyone ! ☺️

I'm beginning and some  inevitable questions are rising:
1) I'm using version 1.3.8, installed via HomeBrew (yes, macOS). Should I stay on it or move to 1.4 or 2 ?
2) I'm studing the "FLTK Programming Manual" and I'm not completely confortable with it. I'm learning better through the codes (examples and test on github) than directely on the manual. Is there any other resouces to study more easy, like tutorials, papers, books etc ?
3) Is this group the best place to make beginner questions or it's better other place ?

Regards. ☺️

wea...@gmail.com

unread,
May 3, 2023, 7:04:34 AM5/3/23
to fltk.general
Hi,

I'm also an FLTK user, the devs may correct me if needed. Actually I find the programming manual quite good, but that may be my personal taste.
1; Don't use FLTK 2. You can read a statement on the website that it is abandoned and should not be used: https://www.fltk.org/images/monthly_commit_activity.svg

2; Greg Ercolano, one of the core developers, has a website with pretty good examples: https://www.seriss.com/people/erco/fltk/. Also he has a youtube channel with FLTK content: https://www.youtube.com/watch?v=wT-6ysL0f7c&list=PL_6WcptSi-JddiX1BegrfsujQ2MBk9jOs

3; I think yes. My advice is that first look for help in the manual, then on the linked material (cheat sheet, youtube). If these don't work then raise you question here or post a small (minimal and complete) working example code with your problem.

Regards,
Antal

Jefferson Costa

unread,
May 3, 2023, 11:14:51 PM5/3/23
to fltkg...@googlegroups.com
Yeap ! The Erco’s site is really good. I’m searching on YT too. His videos are there too.

Thks Antal. ☺️

-- 
You received this message because you are subscribed to the Google Groups "fltk.general" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/bc7af6e1-996a-4a7b-acd4-fb1b623f5b1dn%40googlegroups.com.

Jefferson Costa

unread,
May 4, 2023, 1:53:00 AM5/4/23
to fltkg...@googlegroups.com
Hi everyone ! More questions:

1) I’m confused about event handle. There are methods .handle(), .when(), .callback(). When should I use them ?
2) All callbacks functions have the same sintaxe, like void function (Fl_Widget *, void *) ?
3) All the codes I’m testing until now have the callback functions outside the classes. Could it be inside a class ?

Regards,
Jefferson

wea...@gmail.com

unread,
May 4, 2023, 2:27:35 AM5/4/23
to fltk.general
On Thursday, May 4, 2023 at 7:53:00 AM UTC+2 Jefferson Costa wrote:
Hi everyone ! More questions:

1) I’m confused about event handle. There are methods .handle(), .when(), .callback(). When should I use them ?
when() and callback() are tightly related to each other. callbacks are bound to specific events ("hover", click, release, ...). You can define when your callback is called for a widget, this is done by "when(uchar i)". Here is the list:
For example if you have an Fl_Button then:
"For an Fl_Button object, the following when() values are useful, the default being FL_WHEN_RELEASE:
  • 0: The callback is not done, instead changed() is turned on.
  • FL_WHEN_RELEASE: The callback is done after the user successfully clicks the button, or when a shortcut is typed.
  • FL_WHEN_CHANGED: The callback is done each time the value() changes (when the user pushes and releases the button, and as the mouse is dragged around in and out of the button).
"

You should use handle() if the when()+callback() combo does not cover your needs or you have an Fl_Widget subclass and you want to catch a specific event. I dunno, maybe you don't want "Esc" to exit your application and you catch keypress events or maybe you want to display the mouse position on a statusbar, then  you can catch mouse events in handle() and you can get the mouse position.

2) All callbacks functions have the same sintaxe, like void function (Fl_Widget *, void *) ?
No , there are other callbacks.
Fl_Callback(Fl_Widget *, void *) I use this version to pass generic pointers. For example if a button is pressed (in this case it is the Fl_Widget*) then perform something on the class (e.g. a form) then I storre the class's pointer in the callback and that pointer is passed.
e.g. void mycallback( Fl_Widget* w, void* data)
{
    reinterpret_cast<MyAwesomeClass*>(data)->DoTheActionForButton( dynamic_cast<FlButton*>(w) );
}
I leave it up to you to find out what the other callbacks are for.

3) All the codes I’m testing until now have the callback functions outside the classes. Could it be inside a class ?
It's a C++ question. It is not really related to FLTK. The callback syntax is a good old fashioned function pointer, no classes or namespaces involved. You may use static functions, maybe static class member functions, lambda functions, ... Whathever your compiler allows


Regards,
Jefferson

Albrecht Schlosser

unread,
May 4, 2023, 7:25:58 AM5/4/23
to fltkg...@googlegroups.com
On 5/4/23 05:16 Jefferson Costa wrote:
> Hi everyone ! More questions:
>
> 1) I’m confused about event handle. There are methods .handle(), .when(), .callback(). When should I use them ?

See the good answers from Antal (thanks) in his reply. I'm adding a few
informations. Basically, when() and callback() are used if the basic
functionality of the widget is enough, for instance the button click. As
Antal said, you can set when() the callback is called with when().

If you need more functionality, e.g. highlighting when the mouse cursor
enters the widget you need to subclass the widget and implement your own
handle() method. In the "highlight" example you would handle FL_ENTER
and FL_LEAVE events to change the background color of the widget. Never
forget to call the handle() method of the base class in your own
handle() method.


> 2) All callbacks functions have the same sintaxe, like void function (Fl_Widget *, void *) ?

That's true, the callback function signature, i.e. the function that is
called by FLTK, is always the same [1], but you can store *anything* in
the void* pointer that is used to call your callback function. There are
several different ways to setup your callback, for instance one that
uses a `long` value which you can retrieve in your callback, like this:

button->callback(my_callback, 12345); // set the callback of the button
widget using a 'long' value

// your button callback function:
void my_callback(Fl_Widget *w, void *v) {
  long value = (long)v;
  MyButton* b = (MyButton*)w;
  // do something with the button and the value
}

Note that the data you enter in `button->callback(...)` is stored in the
user_data field of the widget.
https://www.fltk.org/doc-1.4/classFl__Widget.html#a9463920cdace382888f9766781e7aba9

[1] For convenience you can define other callback signatures (see
Fl_Callback, Fl_Callback0, Fl_Callback1) but FLTK can only call one
function type, the one with the (Fl_Widget*, void*) signature.

> 3) All the codes I’m testing until now have the callback functions outside the classes. Could it be inside a class ?

As Antal wrote, the function must be a static function so FLTK can store
a simple function pointer in the widget. However, this can be either a
local function like `static void *my_callback(...)` or it can be a
static member of your widget class. The latter has the advantage that
you can access widget attributes or even call a normal (even protected
of private) member function (method) of the class. This is often done
(particularly by fluid) to forward the callback function to a normal
class method.

Bill Spitzak

unread,
May 4, 2023, 10:56:25 AM5/4/23
to fltkg...@googlegroups.com
In modern C++ compilers lambdas also work, but you are limited to ones that look like plain functions, ie [](FL_Widget*,void*) {...}

--
You received this message because you are subscribed to the Google Groups "fltk.general" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.

Gonzalo Garramuño

unread,
May 4, 2023, 2:26:16 PM5/4/23
to Bill Spitzak, fltkg...@googlegroups.com

El 4/5/23 a las 11:56, Bill Spitzak escribió:
> In modern C++ compilers lambdas also work, but you are limited to ones
> that look like plain functions, ie [](FL_Widget*,void*) {...}
Not for beginners, but you can use Mo_Al_'s excellent functional class
on modern compilers to make lambda's really useful:


#include <FL/Fl_Widget.H>
#include <functional>

template <
    typename W,
    typename =
        typename std::enable_if< std::is_base_of<Fl_Widget,
W>::value>::type>
class Widget : public W
{
    std::function<void(W*)> fn_ = nullptr;

public:
    Widget(int x, int y, int w, int h, const char* l = 0) :
        W(x, y, w, h, l)
    {
    }
    void callback(const std::function<void(W*)>& fn)
    {
        fn_ = fn;
        auto adapter = [](Fl_Widget* w, void* data)
        {
            auto f = (std::function<void(W*)>*)data;
            (*f)((W*)w);
        };
        W::callback(adapter, (void*)&fn_);
    }
};


Usage is then something like:

auto iW = new Widget< Fl_Input >( 0, 0, 320, 240, "Test" );

iW->callback([=](auto o)
{
   std::string text = o->value();

....use lamda captured variables too

});

Gonzalo Garramuño
ggar...@gmail.com

Jefferson Costa

unread,
May 4, 2023, 8:47:02 PM5/4/23
to fltkg...@googlegroups.com
STL and C++11 ahead I do not code so much. So my skills on them are limited. I’ll have to, I know. 😊 One thing at a time.

Jefferson Costa

unread,
May 4, 2023, 8:47:03 PM5/4/23
to fltkg...@googlegroups.com
Yeap. In some codes in “test” I saw “void func(Fl_Wiget *, void *)” outside the classes. But, when inside, I saw “static void* func(Fl_Widget*, void*). Thks. 👍
> --
> You received this message because you are subscribed to the Google Groups "fltk.general" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/bb38e338-565c-4b71-536a-5d58a91ebc96%40online.de.

Jefferson Costa

unread,
May 4, 2023, 8:47:03 PM5/4/23
to fltkg...@googlegroups.com
Ok. I think .when() and .callback() cover everything. Which situation do you think is better .handle() instead ?
The rest, understood. 😊

--
You received this message because you are subscribed to the Google Groups "fltk.general" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.

Jefferson Costa

unread,
May 4, 2023, 8:47:03 PM5/4/23
to fltkg...@googlegroups.com
As I said to Bill, my skills on STL and C++11 ahead are limited, but I’ll get in the future. 😊
> --
> You received this message because you are subscribed to a topic in the Google Groups "fltk.general" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/fltkgeneral/DUyR1eMBXVE/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to fltkgeneral...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/346fcdf6-be83-2cb6-9b38-d7ddc5837f07%40gmail.com.

Greg Ercolano

unread,
May 4, 2023, 9:13:08 PM5/4/23
to fltkg...@googlegroups.com


On 5/4/23 17:35, Jefferson Costa wrote:
Ok. I think .when() and .callback() cover everything. Which situation do you think is better .handle() instead ?

    Using handle() is typically for advanced use when creating custom widgets,
    or customing an existing widget's event management to add new behaviors.

    To use handle() you typically *derive your own class* from an existing widget,
    and you then define the handle() method in your class, and that method will
    be called instead of the widget's own to handle all events (e.g. mouse and keyboard
    events, some window manager events like show+hide, drag+drop events, etc).

    You can then either add your own custom event management and call the
    base widget's handle() to process all events you don't want to handle yourself
    (which is the common use), or you can take over /all/ event management
    yourself, preventing the base widget's event management behavior completely.

    Deriving your own widget is pretty easy, but it's probably not a beginner thing.
    Usually widgets already do what you want and don't need custom event management,
    such as Fl_Button which will invoke your own function when pressed using callbacks.
    If callbacks weren't available, you could use handle() to watch for mouse press events
    and invoke a function or change colors, etc.

Jefferson Costa

unread,
May 5, 2023, 2:31:00 AM5/5/23
to fltkg...@googlegroups.com
Interesting the way you guys write C++ code with FLTK. I saw many global instances and global functions. It’s really easier to code like that. I’m used to make every thing into classes. My example with your code style:

#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>

Fl_Window *window;
Fl_Button *button;

void button_callback(Fl_Widget* widget, void* data) { button->label("Clicked!"); }

void create_ui (void) {
window = new Fl_Window(200, 100, "FLTK Callback Example");
button = new Fl_Button(10, 10, 180, 80, "Click me");
button->callback(button_callback);
window->end();
window->show();
}

int main() {
create_ui();
return Fl::run();
}

Jefferson Costa

unread,
May 5, 2023, 2:31:00 AM5/5/23
to fltkg...@googlegroups.com
Right. 😊
Reply all
Reply to author
Forward
0 new messages