Как реализовать часы обратного отсчета в C++ и FLTK?

Я создаю небольшую игру, используя FLTK и библиотеку Gui из Programming with C++, и я хочу использовать таймер обратного отсчета. FLTK имеет Fl::add_timeout(double t,Callback), что очень полезно. Дело в том, что я хочу использовать эту функцию внутри своего класса, чтобы я мог что-либо изменить внутри окна, когда оно вызывается. Функция должна быть статической, поэтому я не могу получить доступ к окну и внести нужные изменения. Библиотека Gui включает в себя только полезные вещи для программистов-любителей, поэтому я не могу использовать функцию reference_to‹>(). Есть ли идея, как я могу использовать эту функцию или любой другой способ реализовать это? Спасибо за ваше время.

МОЙ КОД:

#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();
}

person Manos Papadakis    schedule 16.08.2015    source источник
comment
Вероятно, вам следует отредактировать свой вопрос, чтобы сделать основные моменты более понятными. Из того, что я собрал, 1. Вы хотите использовать функцию из библиотеки FLTK, которая принимает функцию обратного вызова. 2. Эта функция должна быть статической функцией в стиле c, чтобы передавать ее в качестве обратного вызова. 3. Вы не знаете, как получить доступ к экземпляру класса Game, потому что функция статическая. Простое исправление состоит в том, чтобы передать это в качестве третьего аргумента для add_timeout следующим образом: add_timeout(1.0, TIME, this); Затем в TIME(void *d) вы можете сказать static_cast‹Game*›(d)-›variable.   -  person rationalcoder    schedule 16.08.2015
comment
Большое спасибо! Я не думал использовать такой аргумент void. Спасибо!   -  person Manos Papadakis    schedule 16.08.2015


Ответы (1)


Основные моменты здесь следующие:

  1. Вы хотите использовать функцию (add_timeout)

  2. Он принимает обратный вызов в стиле c, поэтому вы даете ему статическую функцию-член.

  3. Вы не знаете, как получить доступ к переменным экземпляра из статического метода.

Из документации здесь: http://www.fltk.org/doc-2.0/html/index.html, вы можете видеть, что функция add_timeout принимает void* в качестве третьего аргумента, который передается вашему обратному вызову. Быстрым решением здесь будет передача указателя this в функцию add_timeout, а затем его приведение в игру * для доступа к вашим переменным-членам следующим образом:

#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();
}
person rationalcoder    schedule 16.08.2015
comment
Не забудьте выбрать его в качестве ответа!! Ха-ха. - person rationalcoder; 17.08.2015
comment
Вы можете использовать тот же прием для запуска функций-членов с помощью pthread_create/_beginthreadex;) - person Quentin; 17.08.2015