是否可以使用标准 C++ 线程而不是 FLTK 超时来更新 window?
Is it possible to use standard C++ threads instead of FLTK timeouts to update window?
我需要创建一个无需用户交互即可自行运行的简单动画。
有 a bunch of solutions 使用包含的 FLTK 计时器在固定时间段重绘 window 并且该方案在我不移动鼠标或按键的情况下工作正常,但一旦它更改为带有重绘的简单循环() 在 std::thread 中,只有当事件被用户推送到程序时,一切都会中断并重绘。
这是我的代码。如果你懒得启动它,你会看到 updateFunc
每秒稳定地发送到输出中,但是 draw
只在你用鼠标或键盘做某事时出现在那里,因此 window 改变了它颜色。如果这是正常行为,我需要以某种方式改变它。
#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();
}
这是正常行为。但幸运的是,FLTK 已经涵盖了它。
简而言之,您必须在启动线程之前调用 Fl::lock()
,在执行任何更新之前在线程中调用 Fl::lock()
,在更新 GUI 之后调用 Fl::unlock()
,并且 Fl::awake()
而不是 redraw
.
Read the documentation 了解更多信息。
我需要创建一个无需用户交互即可自行运行的简单动画。 有 a bunch of solutions 使用包含的 FLTK 计时器在固定时间段重绘 window 并且该方案在我不移动鼠标或按键的情况下工作正常,但一旦它更改为带有重绘的简单循环() 在 std::thread 中,只有当事件被用户推送到程序时,一切都会中断并重绘。
这是我的代码。如果你懒得启动它,你会看到 updateFunc
每秒稳定地发送到输出中,但是 draw
只在你用鼠标或键盘做某事时出现在那里,因此 window 改变了它颜色。如果这是正常行为,我需要以某种方式改变它。
#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();
}
这是正常行为。但幸运的是,FLTK 已经涵盖了它。
简而言之,您必须在启动线程之前调用 Fl::lock()
,在执行任何更新之前在线程中调用 Fl::lock()
,在更新 GUI 之后调用 Fl::unlock()
,并且 Fl::awake()
而不是 redraw
.
Read the documentation 了解更多信息。