HOWTO = ???->show() in a callback function

32 views
Skip to first unread message

roger tunnicliffe

unread,
Sep 24, 2022, 12:44:52 AM9/24/22
to fltk.general
Not sure how the code below comes across but if any one could help I would appreciate it. Just cannot figure out how to do this (not a C++ programmer).
My main() shows window1. A click on a button invokes but1_Callback which creates window2 that has built a menu and some tabs. The tabs are hidden and when you select a menu option it calls ShowCards() where I want to be able to cards->show. I get a "cards was not declared in this scope" error from g++.

int main(int argc, char **argv) {
     Fl_Window *window1 = new Fl_Window(200,200,"Roger's Window");
            Fl_Radio_Round_Button *but1 = new Fl_Radio_Round_Button(x+15, y+1*20, 70, 15, "SYSTEM");
                but1->callback(but1_Callback);
    window1->show();
.
.
void but1_Callback(Fl_Widget *w, void *data) {
  Fl_Window *window2 = new Fl_Window(625, 450);
       Fl_Menu_Bar *rog = new Fl_Menu_Bar(0, 0, 625, 25);
           rog->menu(menu_items);
        Fl_Tabs *cards = new Fl_Tabs(40,40,300,200);
    cards->hide();
    window2->show();
.
.
Fl_Menu_Item menu_items[] =
{
    {"GeneralJournal",    0,                    0,    0,    FL_SUBMENU,                (uchar)FL_NORMAL_LABEL, 0, 10, FL_YELLOW},
        {"Open",                    FL_ALT+'o',    showCards,    0,    0,             0,                         FL_ITALIC,    10, FL_YELLOW},
        {"Save",                    FL_ALT+'s',    0,    0,    0,                                0,                                         0,    10, FL_YELLOW},
        {"Cancel",                FL_ALT+'a',    0,    0,    FL_MENU_DIVIDER,    0,                                      0,    10, FL_YELLOW},
        {"Exit",                    FL_ALT+'x',    0,    0,    0,                                0,                                            0,    10, FL_YELLOW},
        {0},                                                      
    {0,0,0,0,0,0,0,0,0}
};
.
.
void showCards(Fl_Widget *w, void *data)
{
//    cards->show();
    cout << "How do you show cards" << endl;
}

lifeatt...@gmail.com

unread,
Sep 24, 2022, 11:11:38 AM9/24/22
to fltk.general
The hack approach: declare cards globally and use it as needed.

Fl_Tabs *cards;
void but1_Callback(...) {
...
cards = new Fl_Tabs(40,40,300,200);
...

void showCards(Fl_Widget *w, void *data) {
      cards->show();
}

The FLTK callback data approach: 

void but1_Callback(...) {
...
  Fl_Tabs *cards = new Fl_Tabs(40,40,300,200);
  menu_items[1].user_data_ = cards;  // provide cards pointer as callback data
  rog->menu(menu_items); // need to use menu_items AFTER modifying it
...

void showCards(Fl_Widget *w, void *data) {
  Fl_Tabs *cards = static_cast<Fl_Tabs *>(data);  // please the compiler by casting void * to cards *
  cards->show();
}

Here is a fully "working" version [working in quotes because showCards() is correctly invoked with cards as the data parameter, but cards->show() has no effect...]

#include <FL/Fl_Window.H>
#include <FL/Fl_Radio_Round_Button.H>
#include <FL/Fl_Menu_.H>
#include <FL/Fl_Menu_Bar.H>
#include <FL/Fl_Tabs.H>


void showCards(Fl_Widget *w, void *data) {
    Fl_Tabs *cards = static_cast<Fl_Tabs *>(data);
    cards->show();

}

Fl_Menu_Item menu_items[] =
{
    {"GeneralJournal", 0, 0, 0,    FL_SUBMENU,                (uchar)FL_NORMAL_LABEL, 0, 10, FL_YELLOW},
        {"Open",   FL_ALT+'o',  showCards,  0, 0, 0, FL_ITALIC,    10, FL_YELLOW},
        {"Save",   FL_ALT+'s',    0,    0,    0, 0, 0, 10, FL_YELLOW},
        {"Cancel", FL_ALT+'a',    0,    0,    FL_MENU_DIVIDER, 0, 0, 10, FL_YELLOW},
        {"Exit",   FL_ALT+'x',    0,    0,    0,  0,  0,    10, FL_YELLOW},
        {0},                                                      
    {0,0,0,0,0,0,0,0,0}
};

void but1_Callback(Fl_Widget *w, void *d) {

  Fl_Window *window2 = new Fl_Window(625, 450);
  Fl_Menu_Bar *rog = new Fl_Menu_Bar(0, 0, 625, 25);
  Fl_Tabs *cards = new Fl_Tabs(40,40,300,200);
  cards->hide();
  menu_items[1].user_data_ = cards;
  rog->menu(menu_items);
  window2->show();

}

int main(int argc, char **argv) {
     Fl_Window *window1 = new Fl_Window(200,200,"Roger's Window");
     int x = 0;
     int y = 0;

     Fl_Radio_Round_Button *but1 = new Fl_Radio_Round_Button(x+15, y+1*20, 70, 15, "SYSTEM");
     but1->callback(but1_Callback);
     window1->show();
     Fl::run();
}

imm

unread,
Sep 24, 2022, 1:18:41 PM9/24/22
to General FLTK
As a rider to the previous reply, I'd add that it's probably a good idea to make sure that you "end" window1 before instantiating window2 to avoid getting into weird parenting dependencies between the two windows.

Also, this code would instantiate another window2 every time the button is pressed which might not be the intended behaviour.

--
Ian
From my Fairphone FP3

roger tunnicliffe

unread,
Sep 24, 2022, 6:22:35 PM9/24/22
to fltk.general
Thx guys, I'll try that later today.
Cheers

roger tunnicliffe

unread,
Sep 24, 2022, 6:47:17 PM9/24/22
to fltk.general
The hack approach: declare cards globally and use it as needed.
Fl_Tabs *cards;
void but1_Callback(...) {
cards = new Fl_Tabs(40,40,300,200);

Tried this one quickly and I get a SIGSEV ("Segmentation fault")

roger tunnicliffe

unread,
Sep 24, 2022, 7:04:22 PM9/24/22
to fltk.general
Copy and pasted your working version code and it compiled (after adding FL/Fl.H) okay but when I stepped thru the program "cards->show()" did nothing (nothing displayed) ???

Greg Ercolano

unread,
Sep 24, 2022, 7:08:51 PM9/24/22
to fltkg...@googlegroups.com


On 9/24/22 15:47, roger tunnicliffe wrote:
The hack approach: declare cards globally and use it as needed.
Fl_Tabs *cards;
void but1_Callback(...) {
cards = new Fl_Tabs(40,40,300,200);

Tried this one quickly and I get a SIGSEV ("Segmentation fault")

    Hard to say without seeing all the code.

    This seems to work for me; a modified version of the code lifeatt...@gmail.com's code.

    Try simply copy/pasting this inplace of the code you're using now, and if it works,
    carefully compare it to your old code to see what's wrong.

    In this modified version I added 3 tabs to your tab widget just so it can be seen
    when the Open menu item is chosen.


#include <FL/Fl_Window.H>
#include <FL/Fl_Radio_Round_Button.H>
#include <FL/Fl_Menu_Bar.H>
#include <FL/Fl_Tabs.H>

Fl_Tabs *cards = 0;

void showCards(Fl_Widget *w, void *data) {
    cards->show();
}

Fl_Menu_Item menu_items[] =
{
    // label           shortcut    callback   userdata flags            labeltype               labelfont  labelsize labelcolor
    // --------------  --------    --------   -------- ---------------- ----------------------- ---------  --------- ----------
    {"GeneralJournal", 0,          0,         0,       FL_SUBMENU,      (uchar)FL_NORMAL_LABEL, 0,         10,       FL_YELLOW},
        {"Open",       FL_ALT+'o', showCards, 0,       0,               0,                      FL_ITALIC, 10,       FL_YELLOW},
        {"Save",       FL_ALT+'s', 0,         0,       0,               0,                      0,         10,       FL_YELLOW},
        {"Cancel",     FL_ALT+'a', 0,         0,       FL_MENU_DIVIDER, 0,                      0,         10,       FL_YELLOW},
        {"Exit",       FL_ALT+'x', 0,         0,       0,               0,                      0,         10,       FL_YELLOW},
        {0},                                                      
    {0,0,0,0,0,0,0,0,0}
};

void but1_Callback(Fl_Widget *w, void *d) {
    Fl_Window *window2 = new Fl_Window(625, 450);
      Fl_Menu_Bar *rog = new Fl_Menu_Bar(0, 0, 625, 25);
      rog->menu(menu_items);
      cards = new Fl_Tabs(40,40,300,200);
        // 3 groups makes 3 tabs
        Fl_Group *tab1 = new Fl_Group(40,40+25,300,200-25,"Tab1");
        tab1->end();
        Fl_Group *tab2 = new Fl_Group(40,40+25,300,200-25,"Tab2");
        tab2->end();
        Fl_Group *tab3 = new Fl_Group(40,40+25,300,200-25,"Tab3");
        tab3->end();
      cards->end();
    window2->end();

    cards->hide();
    window2->show();
}

int main(int argc, char **argv) {
    Fl_Window *window1 = new Fl_Window(200,200,"Roger's Window");
    int x = 0;
    int y = 0;
    Fl_Radio_Round_Button *but1 = new Fl_Radio_Round_Button(x+15, y+1*20, 70, 15, "SYSTEM");
    but1->callback(but1_Callback);
    window1->end();
    window1->show();
    return Fl::run();
}


Greg Ercolano

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

On 9/24/22 16:04, roger tunnicliffe wrote:

Copy and pasted your working version code and it compiled (after adding FL/Fl.H) okay but when I stepped thru the program "cards->show()" did nothing (nothing displayed) ???

    That's because no tabs were defined in your Fl_Tabs widget,
    making it effectively 'invisible'.

    To define tabs in the tab widget, you have to add child Fl_Groups,
    one per tab.

    Each child group of Fl_Tabs will be a separate tab; the group's label name
    will be that tab's title, and the contents of the group will be the contents of the tab.

    See the small program I replied with which defines 3 tabs so that
    the tab widget can be seen..

roger tunnicliffe

unread,
Sep 25, 2022, 2:17:03 AM9/25/22
to fltk.general
Thanks guys, I have found the difference but do not understand it..

I had coded:-
       Fl_Tabs *cards = new Fl_Tabs(40,40,300,200);

while your demonstration has coded:-
      cards = new Fl_Tabs(40,40,300,200);

Would be very grateful if you could explain the difference
Cheers
Roger

I am using V1.3.4.9  as supplied by

Operating System: Debian GNU/Linux 10 (buster)
           Kernel: Linux 4.19.0-21-amd64
     Architecture: x86-64

roger tunnicliffe

unread,
Sep 25, 2022, 2:19:40 AM9/25/22
to fltk.general
" That's because no tabs were defined in your Fl_Tabs widget,
    making it effectively 'invisible'."

I did actually have them coded but just did not show that in the code I pasted as I had tried to supply only the relevant information. (obviously that was relevant (lol))

Greg Ercolano

unread,
Sep 25, 2022, 1:14:52 PM9/25/22
to fltkg...@googlegroups.com

On 9/24/22 23:17, roger tunnicliffe wrote:

Thanks guys, I have found the difference but do not understand it..

I had coded:-
       Fl_Tabs *cards = new Fl_Tabs(40,40,300,200);

while your demonstration has coded:-
      cards = new Fl_Tabs(40,40,300,200);

Would be very grateful if you could explain the difference

    You should probably start by learning the C++ language first
    using a tutorial or book so you can get down the basics of the language.
    Then segue into FLTK once you're comfortable with C++.


    With that said, the C++ programming topics you're running into here are:


        "variable scope"        -- once a variable is declared, how long it remains visible
        "variable shadowing"    -- how variables of the same name can 'shadow' each other, depending on scope
       
"pointers"              -- accessing objects and memory via indirection

    When you added the global variable 'cards', but also declared a local variable 'cards'
    and initialized that,
the global variable remains unset, since the local variable shadows it.
    This causes the global
to remain uninitialized.

    And since the variable is a pointer, the machine segfaults your app (crashes it) the moment
    you try to indirect through the uninitialized pointer
(via cards->xxx), causing a memory violation.


    You can read up on C++ variable scoping rules
here: https://codescracker.com/cpp/cpp-scope-rules.htm
    ..and variable shadowing here: https://www.learncpp.com/cpp-tutorial/variable-shadowing-name-hiding/

    But this is kinda sliding off topic for this forum, as these are questions not so much
    about FLTK, and more about the basics of the C++ language itself. I know it's hard to
    know that when you're new to the language, which is why I think it'll help if you learn
    the language first.


Greg Ercolano

unread,
Sep 25, 2022, 1:17:36 PM9/25/22
to fltkg...@googlegroups.com

On 9/24/22 23:19, roger tunnicliffe wrote:

" That's because no tabs were defined in your Fl_Tabs widget,
    making it effectively 'invisible'."

I did actually have them coded but just did not show that in the code I pasted as I had tried to supply only the relevant information. (obviously that was relevant (lol))

    Heh -- yes, it's hard to know what's relevant and what isn't when starting out.

    It's best to try to reduce problems to complete but simple working programs.
    There's a simple example of using tabs on my FLTK cheat page.

roger tunnicliffe

unread,
Sep 25, 2022, 6:18:27 PM9/25/22
to fltk.general
Thanks for the reply Greg.
I understand what was done now. 

Thx
Cheers
Reply all
Reply to author
Forward
0 new messages