Search code examples
c++user-interfacefltk

How to implement a countdown clock in C++ and FLTK?


I create a small game using FLTK and Gui library from Programming with C++ and i want to use a countdown clock-timer. FLTK has the the Fl::add_timeout(double t,Callback) which is very useful. The thing is that i want to use that function inside my class so i can change anything inside the window when it's called. The function has to be static so i can't access the window and make the changes i want. The Gui library includes only the useful things for amatuer programmers so i can't use the function reference_to<>(). Is there any idea how can i use that function or any other way to implement this? Thanks for your time.

MY CODE:

#include"GUI.h"
#include<FL/Fl.h>
#include"Simple_window.h"

class Game : public Window {
   Button *b;
   //variables i need for the window
public:
   Game(Point xy,int w,int h, const string& name) : Window(xy,w,h,name) {         
      b=new Button(Point(100,100),40,20,"Button"cb_button);
      Fl::add_timeout(1.0,TIME);
   }  
   ~Game(){
      delete b;
   }
   static void cb_button(Address,Address addr){
      reference_to<Game>(addr).B();
   }
   void B(){}
   static void TIME(void *d){
      //access to the variables like this->...
      Fl::repeat_timeout(1.0,TIME); 
   }
};

int main(){
  Game win(Point(300,200),400,430,"Game");
  return Fl::run();
}

Solution

  • The main points here are:

    1. You want to use a function (add_timeout)

    2. It takes a c style callback so you are giving it a static member function.

    3. You aren't sure how to access instance variables from the static method.

    From the documentation here: http://www.fltk.org/doc-2.0/html/index.html, you can see the add_timeout function takes a void* as its third argument which is passed to your callback.The quick fix here would be to pass the this pointer to the add_timeout function and then cast it to a Game* to access your member variables like so:

    #include"GUI.h"
    #include<FL/Fl.h>
    #include"Simple_window.h"
    
    class Game : public Window 
    {    
    public:
       Game(Point xy,int w,int h, const string& name) 
              : Window(xy,w,h,name), b(nullptr)
       {         
          b = new Button(Point(100,100),40,20,"Button", cb_button);
          Fl::add_timeout(1.0, callback, (void*)this);
       }
    
       ~Game()
       {
           delete b;
       }
    
       static void cb_button(Address, Address addr)
       {
           reference_to<Game>(addr).B();
       }
    
       void B(){}
    
       static void callback(void *d)
       {
           Game* instance = static_cast<Game*>(d);
           instance->b; // access variables like this->
           Fl::repeat_timeout(1.0,TIME); 
       }
    
    private:
        //variables you need for the window
        Button *b;
    };
    
    int main()
    {
        Game win(Point(300,200),400,430,"Game");
        return Fl::run();
    }