gpt4 book ai didi

c++ - 实现一个进度条类

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:45:07 24 4
gpt4 key购买 nike

我正在使用这本书学习 C++ Programming Principles and Practice Using C++ .第 16 章介绍了通过接口(interface)库使用 FLTK 库的 gui 部分的技术。

本章的练习之一是制作图片的动画,由类中实现的开始和停止按钮控制。对于计时,我发现使用 FLTKs Fl::add_timeoutFl::repeat_timeout 是比进入无限循环并使用 Sleep() 阻塞其他方法更好的解决方案回调。

我没有成功地使用 Fl::add_timeoutFl::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;
}

我找不到如何实现回调函数。我收到评论中所写的编译错误。

如果我将 runco​​unt() 函数设为静态,则对 runco​​unt() 的 4 次调用的编译错误就会消失,但对我来说没有意义使这个函数静态。我在 progBar 调用中收到新错误。

我如何实现这个类,使用启动和停止功能?

我可能缺少一些关于回调函数如何工作和指针使用的知识,这就是我尝试解决这个问题的原因。

最佳答案

回调有签名

void xxx(Fl_Widget*, void*)

ProgressBar 回调具有签名

void ProgressBar::xxx(void*)

解决此问题的一个简单解决方案是创建一个静态函数,该函数依次调用成员函数。以cb_startb为例

// 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);
}

如果将此模型应用于运行计数、cb_startb 和 cb_stopb,它应该会消除大部分编译错误。无论您在哪里使用 runco​​unt 作为参数,都传入静态版本,使用 this 作为 void* 参数。

注意事项:将构造函数中的标签更改为 const std::string& 。

关于c++ - 实现一个进度条类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42456636/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com