我正在學習C++使用書Programming Principles and Practice Using C++。第16章介紹了通過接口庫使用FLTK庫的gui部分的技巧。實現一個進度條類
本章中的練習之一是通過在課堂中實施的開始和停止按鈕控制圖片的移動動畫。對於時機,我發現使用FLTK Fl::add_timeout
和Fl::repeat_timeout
是一個比進入無限循環並使用Sleep()阻止其他回調更好的解決方案。
我沒有實現使用Fl::add_timeout
和Fl::repeat_timeout
工作解決方案成功,但發現了一個例子here使用進度條帶的啓動和停止按鈕:
#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();
}
這個例子編譯並運行良好。
然後我試着把進度條的例子放在一個類中,這就是我卡住的地方。
#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;
}
我找不到如何實現回調函數。我收到了評論中編寫的編譯錯誤。
如果我使runcount()
函數爲靜態,4個調用runcount()
上的編譯錯誤消失,但對我來說使這個函數靜態是沒有意義的。我在progBar調用中遇到新錯誤。
如何實現這個類,使用啓動和停止功能?
我可能錯過了一些關於回調函數如何工作和使用指針的知識,這就是爲什麼我要解決這個問題。