Я использую Fltk для рендеринга графиков openGL. В настоящее время я отлаживаю глобальный массив, который отсортирован по функции heapsort. Моя цель — увидеть после каждой замены элементов в функции heapsort графический обмен элементами. но я не хочу перехватывать событие из FLTK event_handle каждый раз, когда мне нужно перерисовать меня после свопинга и ожидания в точке останова. (функция heapsort и часть рендеринга opengl работают в 2-х разных потоках (если это не обходится без слов)).
Итак, первая попытка была у меня:
Fl::add_timeout(1.0, MyRedrawCallback, (void *)&myWindow);
Fl::run();
void MyRedrawCallback(void *myWindow)
{
MyWindow *pMyWindow;
pMyWindow = (MyWindow *) myWindow;
pMyWindow->redraw();
Fl::repeat_timeout(1.0, MyRedrawCallback, (void *)&pMyWindow);
}
Но каждый раз, когда обратный вызов вызывается во второй раз, я получаю «чтение нарушения доступа»
Я предполагаю, что FL :: run запускает другой поток, так что, возможно, первый раз все еще в том же потоке, так что адрес перерисовки все еще можно использовать, но после этого я нахожусь в другом потоке, и функция по адресу не то, что Я ожидаю?!
Но я уже выбрал другой путь, потому что я не был уверен, что не смогу использовать тайм-аут на этом пути.
Поэтому я искал способ получить событие, например, «установить количество прошедшего времени» или «ничего не происходит …», но я не прав, не так ли?
Наконец, есть ли способ позволить FLTK выполнять команды даже вне EventLop? или есть другой способ решить мою проблему?
Пожалуйста, посмотрите на следующий пример, взятый отсюда: http://seriss.com/people/erco/fltk/#OpenGlInterp
#include <FL/Fl.H>
#include <FL/Fl_Gl_Window.H>
#include <FL/gl.h>
#include <math.h>
//
// Demonstrate interpolating shapes
// erco 06/10/05
//
class Playback : public Fl_Gl_Window {
int frame;
// Linear interpolation between two values based on 'frac' (0.0=a, 1.0=b)
float Linterp(float frac, float a, float b) {
return( a + ( frac * (b - a) ));
}
// Sinusoidal easein/easeout interpolation between two values based on 'frac' (0.0=a, 1.0=b)
float SinInterp(float frac, float a, float b) {
float pi = 3.14159;
frac = (sin(pi/2 + frac*pi ) + 1.0 ) / 2.0; // 0 ~ 1 -> 0 ~ 1
return(Linterp(frac,a,b));
}
// DRAW SIMPLE SHAPE INTERPOLATION
// Interpolation is based on the current frame number
//
void DrawShape(int frame) {
// Calculate a fraction that represents the frame# being shown
float frac = ( frame % 48 ) / 48.0 * 2;
if ( frac > 1.0 ) frac = 2.0-frac; // saw tooth wave: "/\/\/\"
static float a_xy[9][2] = {
{ -.5, -1. }, { 0.0, -.5 }, { -.5, -1. }, { 0.0, -.5 },
{ 0.0, 0.0 },
{ 0.0, -.5 }, { +.5, -1. }, { 0.0, -.5 }, { +.5, -1. },
};
static float b_xy[9][2] = {
{ -.25, -1. }, { -.50, -.75 }, { -.75, -1.0 }, { -.50, -.75 },
{ 0.0, 0.0 },
{ +.50, -.75 }, { +.75, -1.0 }, { +.50, -.75 }, { +.25, -1.0 }
};
// Linterp a and b to form new shape c
float c_xy[9][2];
for ( int i=0; i<9; i++ )
for ( int xy=0; xy<2; xy++ )
c_xy[i][xy] = SinInterp(frac, a_xy[i][xy], b_xy[i][xy]);
// Draw shape
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINE_STRIP);
for ( int i=0; i<9; i++ )
glVertex2f(c_xy[i][0], c_xy[i][1]);
glEnd();
}
// DRAW THE WIDGET
// Each time we're called, assume
//
void draw() {
if (!valid()) {
valid(1);
glLoadIdentity();
glViewport(0,0,w(),h());
}
glClear(GL_COLOR_BUFFER_BIT);
// Draw shape 4x, rotated at 90 degree positions
glPushMatrix();
DrawShape(frame); glRotatef(90.0, 0, 0, 1);
DrawShape(frame); glRotatef(90.0, 0, 0, 1);
DrawShape(frame); glRotatef(90.0, 0, 0, 1);
DrawShape(frame);
glPopMatrix();
// Advance frame counter
++frame;
}
// 24 FPS TIMER CALLBACK
// Called 24x per second to redraw the widget
//
static void Timer_CB(void *userdata) {
Playback *pb = (Playback*)userdata;
pb->redraw();
Fl::repeat_timeout(1.0/24.0, Timer_CB, userdata);
}
public:
// Constructor
Playback(int X,int Y,int W,int H,const char*L=0) : Fl_Gl_Window(X,Y,W,H,L) {
frame = 0;
Fl::add_timeout(1.0/24.0, Timer_CB, (void*)this); // 24fps timer
end();
}
};
int main() {
Fl_Window win(500, 500);
Playback playback(10, 10, win.w()-20, win.h()-20);
win.resizable(&playback);
win.show();
return(Fl::run());
}
Этот пример более / менее делает именно то, что вы хотите. У Грега Эрколано есть больше примеров FLTK на его веб-сайте. Я рекомендую взглянуть на http://seriss.com/people/erco/fltk/ .
Других решений пока нет …