-1

Could anyone break the MyWindow class out into separate MyWindow.h and MyWindow.cpp files from this excellent FLTK example?

I have tried all afternoon. I am stuck on the (void*)this part in the Fl::add_timeout method. I am sure I have other things wrong as well.

I would like to see how the recursion is best handled. Do you MyWindow::RenderImage_CB or leave it as RenderImage_CB?

Adding the code here for convenience.

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/fl_draw.H>
#include <stdio.h>
#include <time.h>

#define XSIZE 500
#define YSIZE 500
#define UPDATE_RATE 0.05     // update rate in seconds

// Demonstrate how to display a pixel buffer in FLTK

// WINDOW CLASS TO HANDLE DRAWING IMAGE
class MyWindow : public Fl_Double_Window {
    unsigned char pixbuf[YSIZE][XSIZE][3];              // image buffer

    // FLTK DRAW METHOD
    void draw() {
        fl_draw_image((const uchar*)&pixbuf, 0, 0, XSIZE, YSIZE, 3, XSIZE*3);
    }

    // TIMER CALLBACK: CALLED TO UPDATE THE DRAWING
    static void RenderImage_CB(void *userdata) {
        MyWindow *win = (MyWindow*)userdata;
        win->RenderImage();
        Fl::repeat_timeout(UPDATE_RATE, RenderImage_CB, userdata);
    }

public:
    // CTOR
    MyWindow(int w, int h, const char *name=0) : Fl_Double_Window(w,h,name) {
        end();
        RenderImage();                   // show first drawing
        // Start timer updating
        Fl::add_timeout(UPDATE_RATE, RenderImage_CB, (void*)this);
    }

    // PLOT A PIXEL AS AN RGB COLOR INTO THE PIXEL BUFFER
    void PlotPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b) {
        pixbuf[y][x][0] = r;
        pixbuf[y][x][1] = g;
        pixbuf[y][x][2] = b;
    }

    // MAKE A NEW PICTURE IN THE PIXEL BUFFER, SCHEDULE FLTK TO DRAW IT
    void RenderImage() {
        static unsigned char drawcount = 0;
        for ( int x=0; x<XSIZE; x++ )
            for ( int y=0; y<YSIZE; y++ )
                PlotPixel(x, y, x+drawcount, y+drawcount, x+y+drawcount);
        ++drawcount;
        redraw();
    }
};

int main(int argc, char**argv) {
    Fl::visual(FL_RGB);         // prevents dithering on some systems
    MyWindow *win = new MyWindow(XSIZE, YSIZE);
    win->show();
    return(Fl::run());
}

Separated this way gives a compiler error:

main.cpp

#include "MyWindow.h"

int main(int argc, char**argv) {
    Fl::visual(FL_RGB);         // prevents dithering on some systems
    MyWindow *win = new MyWindow(XSIZE, YSIZE);
    win->show();
    return(Fl::run());
}

MyWindow.h

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/fl_draw.H>
#include <stdio.h>
#include <time.h>

#define XSIZE 500
#define YSIZE 500
#define UPDATE_RATE 0.05     // update rate in seconds

// WINDOW CLASS TO HANDLE DRAWING IMAGE
class MyWindow : public Fl_Double_Window {
    unsigned char pixbuf[YSIZE][XSIZE][3];              // image buffer

    // FLTK DRAW METHOD
    void draw();

    // TIMER CALLBACK: CALLED TO UPDATE THE DRAWING
    void RenderImage_CB(void *userdata);

public:
    // CTOR
    MyWindow(int w, int h, const char *name=0) : Fl_Double_Window(w,h,name){};

    // PLOT A PIXEL AS AN RGB COLOR INTO THE PIXEL BUFFER
    void PlotPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b);

    // MAKE A NEW PICTURE IN THE PIXEL BUFFER, SCHEDULE FLTK TO DRAW IT
    void RenderImage();
};

MyWindow.cpp

#include "MyWindow.h"

void MyWindow::draw() {
    fl_draw_image((const uchar*)&pixbuf, 0, 0, XSIZE, YSIZE, 3, XSIZE*3);
}

void MyWindow::RenderImage_CB(void *userdata) {
    MyWindow *win = (MyWindow*)userdata;
    win->RenderImage();
    Fl::repeat_timeout(UPDATE_RATE, MyWindow::RenderImage_CB, userdata);
}

MyWindow::MyWindow(int w, int h, const char *name) : Fl_Double_Window(w,h,name) {
    end();
    MyWindow::RenderImage();                   // show first drawing
    // Start timer updating
    Fl::add_timeout(UPDATE_RATE, MyWindow::RenderImage_CB, (void*)this);
}

void MyWindow::PlotPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b) {
    pixbuf[y][x][0] = r;
    pixbuf[y][x][1] = g;
    pixbuf[y][x][2] = b;
}

void MyWindow::RenderImage() {
    static unsigned char drawcount = 0;
    for ( int x=0; x<XSIZE; x++ )
        for ( int y=0; y<YSIZE; y++ )
            PlotPixel(x, y, x+drawcount, y+drawcount, x+y+drawcount);
    ++drawcount;
    redraw();
}

Using the above my first error is:

MyWindow.cpp:10:71: error: no matching function for call to 'Fl::repeat_timeout(double, <unresolved overloaded function type>, void*&)'
     Fl::repeat_timeout(UPDATE_RATE, MyWindow::RenderImage_CB, userdata);
sadsquonk
  • 1
  • 3
  • What have you tried so far? The process should be mechanical and straightforward; the fact that one of the member functions is `static` does not make much of a difference. Copy the class definition into a header file. In the header, remove all definitions and replace by a semicolon. In the cpp file, remove the surrounding `class`, declarations of data members, and public/private, and add `MyClass::` on all functions and remove the `static` from the declaration. – Thomas Aug 10 '20 at 11:15
  • The solution depends on what you need. The simplest answer would be just moving the whole class declaration to an .h file. All modules which include it would use the same declaration. However, this implicitly makes all methods inlined. If you don't like this, do as Thomas said above: put a class declaration with all methods declarations in .h and definitions of methods in .cpp file. – CiaPan Aug 10 '20 at 12:53

1 Answers1

0

This compiles and runs:

main.cpp

#include "MyWindow.h"

int main(int argc, char**argv) {
    Fl::visual(FL_RGB);         // prevents dithering on some systems
    MyWindow *win = new MyWindow(XSIZE, YSIZE);
    win->show();
    return(Fl::run());
}

MyWindow.h

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/fl_draw.H>
#include <stdio.h>
#include <time.h>

#define XSIZE 500
#define YSIZE 500
#define UPDATE_RATE 0.05     // update rate in seconds

// WINDOW CLASS TO HANDLE DRAWING IMAGE
class MyWindow : public Fl_Double_Window {
    unsigned char pixbuf[YSIZE][XSIZE][3];              // image buffer

    // FLTK DRAW METHOD
    void draw();

    // TIMER CALLBACK: CALLED TO UPDATE THE DRAWING
    static void RenderImage_CB(void *userdata);

public:
    // CTOR
    MyWindow(int w, int h, const char *name=0);// : Fl_Double_Window(w,h,name){};

    // PLOT A PIXEL AS AN RGB COLOR INTO THE PIXEL BUFFER
    void PlotPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b);

    // MAKE A NEW PICTURE IN THE PIXEL BUFFER, SCHEDULE FLTK TO DRAW IT
    void RenderImage();
};

MyWindow.cpp

#include "MyWindow.h"

MyWindow::MyWindow(int w, int h, const char *name) : Fl_Double_Window(w,h,name) {
    end();
    MyWindow::RenderImage();                   // show first drawing
    // Start timer updating
    Fl::add_timeout(UPDATE_RATE, MyWindow::RenderImage_CB, (void*)this);
}

void MyWindow::draw() {
    fl_draw_image((const uchar*)&pixbuf, 0, 0, XSIZE, YSIZE, 3, XSIZE*3);
}

void MyWindow::RenderImage_CB(void *userdata) {
    MyWindow *win = (MyWindow*)userdata;
    win->RenderImage();
    Fl::repeat_timeout(UPDATE_RATE, MyWindow::RenderImage_CB, userdata);
}

void MyWindow::PlotPixel(int x, int y, unsigned char r, unsigned char g, unsigned char b) {
    pixbuf[y][x][0] = r;
    pixbuf[y][x][1] = g;
    pixbuf[y][x][2] = b;
}

void MyWindow::RenderImage() {
    static unsigned char drawcount = 0;
    for ( int x=0; x<XSIZE; x++ )
        for ( int y=0; y<YSIZE; y++ )
            PlotPixel(x, y, x+drawcount, y+drawcount, x+y+drawcount);
    ++drawcount;
    redraw();
}
sadsquonk
  • 1
  • 3