Syntax Variations (My original post seemed to disappear

20 views
Skip to first unread message

roger tunnicliffe

unread,
Sep 16, 2022, 2:36:17 AM9/16/22
to fltk.general
Hi, new to FLTK (and FLUID) and really like it. Have figured out a few things but not sure why there is syntax variations between what FLUID produces and example code I can find. I do not know much about C++ or ObjectOrientation (I am an assembler programmer) but think it might be more about that then anything else. I've posted the following example:-

int main()
{
    Fl_Window fltkWindow(300, 400, "fltk Window");
        Fl_Button fltkButton (25, 20, 70, 50, "button1");
        Fl_Button *fluidButton = new Fl_Button(25, 80, 70, 50, "button2");
    fltkWindow.end();        // Not really required

    Fl_Window *fluidWindow = new Fl_Window(245, 255, "fluidWindow");
        Fl_Group* o = new Fl_Group(25, 20, 180, 220);
              { new Fl_Button(25, 20, 70, 50, "button1");
                new Fl_Button(25, 80, 70, 50, "button2");
              new Fl_Button(25, 140, 70, 50, "button3");
            }
    fluidWindow->end();
    fltkWindow.show();
    fluidWindow->show();
    return Fl::run();
}

It seems you can code (at least) 2 different ways. I am guessing FLUID is creating instances or a class while the other way is not. Can anyone give me a quick idea of what's going on.
Thanks in advance.
Cheers
Roger

Greg Ercolano

unread,
Sep 16, 2022, 3:34:23 AM9/16/22
to fltkg...@googlegroups.com


On 9/15/22 22:42, roger tunnicliffe wrote:
Hi, new to FLTK (and FLUID) and really like it. Have figured out a few things but not sure why there is syntax variations between what FLUID produces and example code I can find. I do not know much about C++ or ObjectOrientation (I am an assembler programmer) but think it might be more about that then anything else. I've posted the following example:-

    If you mean, for instance, these two ways to declare a button:

        Fl_Button fltkButton(25, 20, 70, 50, "button1");

        Fl_Button *fluidButton = new Fl_Button(25, 80, 70, 50, "button2");

    Both declare instances of a button:

    The first form declares an instance of an Fl_Button class called 'fltkButton'.
    This instance and name has a lifetime up to the closing brace for the block
    of code it's declared in (which is main()). When the closing brace is reached,
    the instance is automatically destroyed. This is similar to declaring a
    variable in C; if you declare 'int x = 0;' it will be created and visible up
    until the closing brace.

    The second form declares a pointer called fluidButton, and initializes it
    to point to an instance of Fl_Button created with 'new'. The instance's
    lifetime makes it available until the pointer is destroyed with 'delete',
    and the pointer's lifetime is only visible until the closing brace, unless
    the pointer is saved somewhere else.
    Both button instances are 'initialized' with the x,y,w,h values and the
    button name ("button1" for the first, and "button2" for the second).
    And due to how FLTK operates, the buttons are automatically parented
    to the window that is declared above the buttons. In fact any FLTK widgets
    created after the declaration of the window will automatically be parented
    to the window, up until the window's end() is invoked, ending the auto-parenting.

    It would help if you're familiar with plain old C, as creating instances of classes
    (e.g. Fl_Button foo(..)) is very much like instancing simple integer variables
    (e.g. int foo = 0;).

    And instancing pointers to classes (e.g. Fl_Button *pfoo = new Fl_Button(..))
    is very similar to instancing pointers to integers (e.g. 'int x = 0; int *px = &x;')

    C++ classes are just more complex objects than an 'int', but are
    created/destroyed in much the same way.

    I know assembly too, and I'm not sure there's an easy way to describe
    the above C and C++ concepts in assembly, as automatic variables
    and variable name scope aren't really built into assembly language,
    though these concepts can kinda/sorta be supported by the assembler,
    and/or limiting variable scope to modules (.obj's) in the same way
    variable scope is limited to {} blocks in C/C++.

Greg Ercolano

unread,
Sep 16, 2022, 3:37:45 AM9/16/22
to fltkg...@googlegroups.com

On 9/15/22 22:42, roger tunnicliffe wrote:

Subject: ..My original post seemed to disappear..

    It didn't disappear, it just takes time to be moderated and approved.

imm

unread,
Sep 16, 2022, 5:40:51 AM9/16/22
to General FLTK
Yeah, I had a dentist appointment

Greg Ercolano

unread,
Sep 16, 2022, 4:44:25 PM9/16/22
to fltkg...@googlegroups.com

On 9/16/22 02:45, imm wrote:

On 9/15/22 22:42, roger tunnicliffe wrote:
Subject: ..My original post seemed to disappear..

    It didn't disappear, it just takes time to be moderated and approved.
Yeah, I had a dentist appointment

    Heh, you usually always beat me to moderation these days..

roger tunnicliffe

unread,
Sep 16, 2022, 5:58:54 PM9/16/22
to fltk.general
Thx for the reply (sorry can't see your name).

I am wondering then what would be the use cases for each particular syntactical version. ie.

When and why would i use this code....
        Fl_Button fltkButton(25, 20, 70, 50, "button1");
             noting it requires fltkButton.labelsize(12);
as opposed to this code....
        Fl_Button *fluidButton = new Fl_Button(25, 80, 70, 50, "button2"); 
            noting it requires fltkButton->labelsize(12);

Thx
Roger Tunnicliffe
Cheers

P.S. The more I play around with FLTK/FLUID the more I like it. Very simple to understand. 
I have my own project (www.languageONE.com.au) and have been looking into a GUI. I am 
hoping FLTK would fit the bill.

Rob McDonald

unread,
Sep 16, 2022, 7:10:31 PM9/16/22
to fltk.general
On Friday, September 16, 2022 at 2:58:54 PM UTC-7 
Thx for the reply (sorry can't see your name).

As Greg Ercolano alluded, these differences have nothing to do with FLTK, but they are inherent to C++.  You could make the same choice for any object or variable in C++.

On this list, top-posting is frowned upon.

Google Groups is not great at keeping people's names attached to their posts.  For better or worse, there are about four kind souls who answer almost all of the questions on this list (I am not one of those people.  My role here is to ask questions.).  So, if you hang around for a little while, you'll quickly figure out who the players are and where their individual expertise and interest falls.

I am wondering then what would be the use cases for each particular syntactical version. ie.

When and why would i use this code....
        Fl_Button fltkButton(25, 20, 70, 50, "button1");
             noting it requires fltkButton.labelsize(12);
as opposed to this code....
        Fl_Button *fluidButton = new Fl_Button(25, 80, 70, 50, "button2"); 
            noting it requires fltkButton->labelsize(12);


The first is a 'local' instance.  It exists within the scope of the {} brackets it was created in.  It will automatically be destroyed when you cross the closing bracket}.

The second is a pointer to an instance.  It will exist until you use the delete operator on the pointer or the program terminates.  The pointer itself is an integer type (size depending on your machine architecture) that refers to the memory address for the object.

fltkButton.labelsize(12);  // fltkButton is an instance of class Fl_Button.  You access method of an instance with a . operator

fluidButton->labelsize(12); // fluidButton is a pointer to an instance of class Fl_Button.  fluidButton is an integer type that contains a memory address.  You dereference the memory address and then access a method of the instance with a -> operator

Typically, if you use the assignment operator '=' with an instance of an instance, a deep copy of that instance is made.  That can require allocating significant memory.  The same thing happens if you pass that instance to a function/method, or return an instance from a function / method.  Since you are passing by copy, you have pass by value semantics.

When you use the assignment operator '=' with a pointer to an instance, a copy of the pointer is made -- of course that copy points to the same memory address.  That allocation is cheap / simple because the pointer is a single integer value.  Passing a pointer to a function / method, and returning a pointer all are very cheap because you are passing around a single memory address.  However, all of this has pass by reference semantics -- any operations performed in any context can potentially change single instance of the variable pointed to.  Likewise, if one of the routines 'delete's the pointer, the instance is destroyed and all of the pointers become invalid.

Again -- none of this is FLTK.  This is all C++ (and most of it is common to (or at least very familiar to) pure C).

Rob






 

Greg Ercolano

unread,
Sep 16, 2022, 7:25:19 PM9/16/22
to fltkg...@googlegroups.com


On 9/16/22 14:48, roger tunnicliffe wrote:
Thx for the reply (sorry can't see your name).

I am wondering then what would be the use cases for each particular syntactical version. ie.

When and why would i use this code....
        Fl_Button fltkButton(25, 20, 70, 50, "button1");
             noting it requires fltkButton.labelsize(12);
as opposed to this code....
        Fl_Button *fluidButton = new Fl_Button(25, 80, 70, 50, "button2"); 
            noting it requires fltkButton->labelsize(12);

    Probably no good reason, other than it's shorter.

    If you're new to C++, I'd suggest always using 'new' to create
    FLTK widgets so you don't have to worry about widgets going
    out of scope prematurely.

lifeatt...@gmail.com

unread,
Sep 17, 2022, 8:47:32 PM9/17/22
to fltk.general
I am wondering then what would be the use cases for each particular syntactical version. ie.

When and why would i use this code....
        Fl_Button fltkButton(25, 20, 70, 50, "button1");
             noting it requires fltkButton.labelsize(12);
as opposed to this code....
        Fl_Button *fluidButton = new Fl_Button(25, 80, 70, 50, "button2"); 
            noting it requires fltkButton->labelsize(12);
I use the second form frequently because I'm often working with control interactions. E.g. if I have a button in my GUI which impacts 
other controls (such as a 'Reset' button). As alluded to in erco's first reply: "unless the pointer is saved somewhere else." - pointers to 
the impacted controls need to be kept around so (in this case) the button callback can "talk" to them. So a simple, contrived example:

// Kept pointers
Fl_Int_Input *inpDollarAmount;
Fl_Int_Input *inpOther;
...
// GUI construction
inpDollarAmount = new Fl_Int_Input(25, 20, 75, 25, "Amount:");
Fl_Button *btnReset = new Fl_Button(25, 50, 75, 25, "Reset");
btnReset->callback(onReset);
...
// Reset button callback: clears all input controls
void onReset(Fl_Widget *w, void *d)
{  
    inpDollarAmount->value(0);   // callback can't access the control without the pointer
    inpOther->value(0);
}

 

Albrecht Schlosser

unread,
Sep 18, 2022, 5:44:21 AM9/18/22
to fltkg...@googlegroups.com
On 9/17/22 01:25 Greg Ercolano wrote:
On 9/16/22 14:48, roger tunnicliffe wrote:
Thx for the reply (sorry can't see your name).

I am wondering then what would be the use cases for each particular syntactical version. ie.

When and why would i use this code....
        Fl_Button fltkButton(25, 20, 70, 50, "button1");
             noting it requires fltkButton.labelsize(12);
as opposed to this code....
        Fl_Button *fluidButton = new Fl_Button(25, 80, 70, 50, "button2"); 
            noting it requires fltkButton->labelsize(12);

    Probably no good reason, other than it's shorter.

There may be cases where you want a C++ object to be deleted when the current scope is left. One (mostly internal) FLTK example is Fl_Widget_Tracker which is usually allocated on the stack (a local variable) so it is automatically deleted at the end of the function or method.


    If you're new to C++, I'd suggest always using 'new' to create
    FLTK widgets so you don't have to worry about widgets going
    out of scope prematurely.

It should be noted that the pointer you use when allocating with `new` would also go out of scope eventually and thus it can't be used later unless saved as Kevin described in another reply.

An important point here is that the "automatic parenting mode" of FLTK usually adds a widget to the current group (window) so you can "forget" the pointer because you will likely not use it later. Working example code with comments below:

#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
int main(int argc, char **argv) {
// allocate window on stack: scope/lifetime is main()
Fl_Window window(240, 140, "main window");
{ // introduce a local block (scope)
// allocate button b with operator new
Fl_Button *b = new Fl_Button(20, 20, 200, 100, "Hello, world!");
// use the pointer b
b->color(FL_YELLOW);
// pointer b goes out of scope but the window keeps a pointer
// to the button and the widget will not (yet) be destroyed
}
window.end(); // end automatic parenting
window.show(argc, argv);
return Fl::run();
// the window 'window' will be deleted after main() and
// its destructor will also delete the button
}
You can build this example program with `fltk-config --compile demo.cxx`.

If you would allocate the button on the stack in the local scope rather than using `new` it would be deleted at the end of the block and it would be removed from the window at that time (try this).

I didn't bother to add a button callback, you need to close the window with the window's close ('X') button or hit the 'Esc' key to end the program.

I hope this helps.

david allen

unread,
Sep 18, 2022, 3:54:16 PM9/18/22
to fltk.general
The following illustrates access through the windows' child array

// Compile with `fltk-config --compile child.cpp`.


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

int main(int argc, char **argv)
  {
  // allocate window on stack: scope/lifetime is main()
  Fl_Window window(240, 140, "main window");
  new Fl_Button(20, 20, 200, 100, "Hello, world!");
  window.end(); // end automatic parenting

  Fl_Button* but = (Fl_Button*) window.child(0);
  but->color(FL_RED);
Reply all
Reply to author
Forward
0 new messages