I am learning c++ using the book Programming Principles and Practice Using C++. Chapter 16 covers techniques using the gui part of FLTK library via an interface library.
One of the exercises in this chapter is to animate movement of a picture, controlled by a start and stop button implemented in a class. For timing I found that use of FLTKs Fl::add_timeout
and Fl::repeat_timeout
is a better solution than going in to an infinite loop and use Sleep(), blocking other callbacks.
I did not succeed in implementing a working solution using Fl::add_timeout
and Fl::repeat_timeout
, but found an example here using a progress bar with a start and stop button:
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Progress.H>
#include <FL/Fl_Button.H>
Fl_Progress* progBar;
void runcount(void*)
{
if (progBar->value() == progBar->maximum())
{
Fl::remove_timeout(runcount);
progBar->value(0);
}
else
{
Fl::repeat_timeout(1, runcount);
progBar->value(progBar->value() + 1);
}
}
void cb_startb(void)
{
Fl::add_timeout(1, runcount);
}
void cb_stopb(void)
{
Fl::remove_timeout(runcount);
}
int main (int argc, char *argv[])
{
Fl_Double_Window window(200,70,"ProgressBar Test");
progBar = new Fl_Progress(5, 10, window.w()-10, 20);
progBar->box(FL_SHADOW_BOX);
progBar->selection_color((Fl_Color)4);
progBar->minimum(0);
progBar->maximum(10);
Fl_Button* start_button = new Fl_Button(10, 40, 80, 20, "START");
start_button->box(FL_SHADOW_BOX);
start_button->callback((Fl_Callback*)cb_startb,(void*)"start");
Fl_Button* stop_button = new Fl_Button(110, 40, 80, 20, "STOP");
stop_button->box(FL_SHADOW_BOX);
stop_button->callback((Fl_Callback*)cb_stopb,(void*)"stop");
window.end();
window.show(argc, argv);
return Fl::run();
}
This example compiles and works fine.
I then tried to put the progress bar example together in a class, and this is where I am stuck.
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Progress.H>
#include <FL/Fl_Button.H>
#include <string>
class ProgressBar : public Fl_Double_Window {
public:
ProgressBar(int w, int h, const std::string label)
: Fl_Double_Window{ w,h,label.c_str() }
{
progBar = new Fl_Progress(5, 10, 10, 20);
progBar->box(FL_SHADOW_BOX);
progBar->selection_color((Fl_Color)4);
progBar->minimum(0); // set range: 0-10
progBar->maximum(10);
start_button = new Fl_Button(10, 40, 80, 20, "START");
start_button->box(FL_SHADOW_BOX);
start_button->callback((Fl_Callback*)cb_startb, (void*)"start"); //compile error: 'type-cast':cannot convert
//from 'overloaded-function'..
stop_button = new Fl_Button(110, 40, 80, 20, "STOP");
stop_button->box(FL_SHADOW_BOX);
stop_button->callback(static_cast<Fl_Callback*>(cb_stopb), (void*)"stop");//(Fl_Callback*)cb_stopb
//compile error: 'type-cast':cannot convert from 'overloaded-function'..
}
~ProgressBar()
{
delete progBar;
delete start_button;
delete stop_button;
}
private:
void runcount(void*)
{
if (progBar->value() == progBar->maximum())
// max reached, stop timer and reset pregress bar to 0
{
Fl::remove_timeout(runcount); // non-standard syntax, use & to create a pointer to member
progBar->value(0);
}
else
// timer running, recursive calling this function - increase progress bar by 1.
{
Fl::repeat_timeout(0.1, runcount); ///compile error: non-standard syntax, use & to create a pointer to member
progBar->value(progBar->value() + 1);
}
}
void cb_startb(void)
{
Fl::add_timeout(1, runcount);///compile error: non-standard syntax, use & to create a pointer to member
}
void cb_stopb(void)
{
Fl::remove_timeout(runcount);///compile error: non-standard syntax, use & to create a pointer to member
}
Fl_Button* start_button;
Fl_Button* stop_button;
Fl_Progress* progBar;
};
int main()
{
ProgressBar* progBar = new ProgressBar{200, 700,"Progress bar" };
progBar->end();
progBar->show();
return Fl::run();
delete progBar;
}
I cannot find out how to implement the callback functions. I get the compile errors as written in the comments.
If I make the runcount()
function static, the compile error on the 4 calls to runcount()
disappears, but it doesn’t make sense to me to make this function static. I get new errors on the progBar calls.
How can I implement this class, to use a start and stop function?
I am probably missing some knowledge on how callback function works and the use of pointers, which is why I am trying to work this out.
Use the <progress> tag to create a progress bar in HTML. The HTML <progress> tag specifies a completion progress of a task. It is displayed as a progress bar. The value of progress bar can be manipulated by JavaScript.
You have to use class . active to create animated progress bar.
A progress bar is a graphical control element used to visualize the progression of an extended computer operation, such as a download, file transfer, or installation. Sometimes, the graphic is accompanied by a textual representation of the progress in a percent format.
The callback has the signature
void xxx(Fl_Widget*, void*)
The ProgressBar callbacks have the signature
void ProgressBar::xxx(void*)
A simple solution to get around this problem is to create a static function, which, in turn calls the member function. Using cb_startb as an example
// Where you are getting the compilation error
start_button->callback(_cb_startb, this);
...
// Create a static version of your function
static void _cb_startb(Fl_Widget*, void* self)
{
reinterpret_cast<ProgressBar*>(self)->cb_startb();
}
// This is the member function
void cb_startb()
{
// do the same thing for runcount
Fl::add_timeout(1, _runcount, this);
}
If you apply this model to runcount, cb_startb and cb_stopb, it should get rid of most of your compile errors. Wherever you are using runcount as a parameter, pass in the static version, using this as the void* parameter.
Minor note: change the label in the constructor to a const std::string& .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With