强制FLTK重绘没有事件句柄

时间:2013-01-28 15:34:49

标签: c++ event-handling redraw fltk

我正在使用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甚至在eventloop之外执行命令?还是有另一种方法来解决我的问题?

1 个答案:

答案 0 :(得分:3)

请查看以下示例: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());
}

此示例更多/更少完全符合您的要求。 Greg Ercolano在他的网站上有更多的FLTK例子。我建议您查看http://seriss.com/people/erco/fltk/