是否可以使用标准 C++ 线程而不是 FLTK 超时来更新窗口?
Posted
技术标签:
【中文标题】是否可以使用标准 C++ 线程而不是 FLTK 超时来更新窗口?【英文标题】:Is it possible to use standard C++ threads instead of FLTK timeouts to update window? 【发布时间】:2017-12-02 20:04:47 【问题描述】:我需要创建一个无需用户交互即可自行完成的简单动画。 有a bunch of solutions 使用包含的 FLTK 计时器在固定时间段内重绘窗口,并且该方案工作正常,无需我移动鼠标或按键,但只要它在 std:: 中使用 redraw() 更改为简单循环:线程,只有在用户将事件推送到程序时,一切都会中断和重绘。
这是我的代码。如果您费心启动它,您会看到updateFunc
每秒稳定地向输出发送垃圾邮件,但draw
仅在您使用鼠标或键盘执行某些操作时才会出现在那里,因此窗口会改变其颜色。如果这是正常行为,我需要以某种方式对其进行更改。
#include <bits/stdc++.h>
using namespace std;
#include <FL/Fl.h>
#include <FL/gl.h>
#include <FL/Fl_Gl_Window.h>
chrono::time_point<chrono::system_clock> execStart;
void log(const char* fmt, ...)
va_list arg;
va_start(arg,fmt);
fprintf(stderr,"[%10.3f] ",chrono::duration_cast<chrono::milliseconds>(
chrono::system_clock::now()-execStart
).count()/1000.0);
vfprintf(stderr,fmt,arg);
fprintf(stderr,"\n");
va_end(arg);
double rand01() return (double)rand()/RAND_MAX;
class Window: public Fl_Gl_Window
private:
thread updateThread;
void updateFunc()
while (1)
log("%s",__func__);
this_thread::sleep_for(1s);
redraw();
protected:
void draw()
log("%s",__func__);
glClearColor(rand01(),rand01(),rand01(),1);
glClear(GL_COLOR_BUFFER_BIT);
public:
Window(int x,int y,int w,int h,const char* s):
Fl_Gl_Window(x,y,w,h,s),
updateThread(&Window::updateFunc,this)
Window(): Window(320,240,800,600,"FLTK OpenGL test")
;
int main()
execStart=chrono::system_clock::now();
log("execution started");
srand(time(0));
Window *wnd=new Window();
wnd->show();
return Fl::run();
【问题讨论】:
【参考方案1】:这是正常行为。但幸运的是,FLTK 已经涵盖了它。
简而言之,您必须在启动线程之前调用Fl::lock()
,在进行任何更新之前在线程中调用Fl::lock()
,在更新GUI 之后调用Fl::unlock()
,并使用Fl::awake()
而不是redraw
。
Read the documentation 了解更多信息。
【讨论】:
很好,很不错!只是为了确保,是否也可以等待 FLTK 从工作线程完成绘图?因为我的线程中有很多多余的循环迭代,这不是很好,所以我想避免这种情况。 FLTK 只有一半。在后台线程上,您可以使用Fl::awake(Fl_Awake_Handler cb, void* userdata)
调用在渲染线程上调度一个函数,并等待完成。在该函数中调用redraw
,并通知后台线程它已完成。需要自己实现wait+notifications,现代C++方式大概是std::promise<void>
或者如果你要发布多个请求,你可以使用 std::queue 来获取结果,使用 std::mutex 来保护它,使用 std::condition_variable 来实现睡眠/唤醒。跨度>
以上是关于是否可以使用标准 C++ 线程而不是 FLTK 超时来更新窗口?的主要内容,如果未能解决你的问题,请参考以下文章
如何让 Octave 默认使用“gnuplot”而不是“fltk”?