If the intent is to do "incremental" drawing then using an Fl_Offscreen is the
best way to go (IMHO of course...)
This (below) is the example I usually post at this point when this topic comes
up...
Note that this does not actually use threads but simply uses a timer to
simulate the background thread - converting to really use threads should be
trivial.
Hope this code helps - it is perhaps longer and more verbose that would be
ideal for true clarity!
----------
/*****************************************************************************/
// fltk-config --compile offscreen-demo.cxx
/* Standard headers */
#include <stdlib.h>
#include <time.h> // use time() in random code below
/* Fltk headers */
#include <Fl/Fl.h>
#include <FL/Fl_Double_Window.H>
#include <FL/x.H>
#include <Fl/Fl_Box.H>
#include <Fl/fl_draw.h>
// The main window for the demo
static Fl_Double_Window *main_window = 0;
// The offscreen surface
static Fl_Offscreen oscr = 0; // the surface
static int os_w = 0, os_h = 0; // the surface's dimensions
/*****************************************************************************/
/* This class provides a view into the offscreen surface */
class oscr_box : public Fl_Box {
void draw();
int handle(int event);
protected:
int x_old, y_old; /* previous x,y during a drag operation */
int drag_state; /* non-zero if a drag is in progress */
int page_x, page_y; /* current view position */
public:
oscr_box(int x, int y, int w, int h);
};
/*****************************************************************************/
/* Constructor */
oscr_box::oscr_box(int x, int y, int w, int h) : Fl_Box(x,y,w,h){
x_old = y_old = 0;
drag_state = 0;
page_x = page_y = 750;
} // Constructor
/*****************************************************************************/
void oscr_box::draw() {
int wd = w();
int ht = h();
int xo = x();
int yo = y();
// first clear out the view to a flat grey - this is
// redundant if we know the offscreen will fill the view
fl_color(fl_gray_ramp(19));
fl_rectf(xo, yo, wd, ht);
// now draw the view
if(oscr) { // offscreen exists
// blit the required view from the offscreen onto the box
fl_copy_offscreen(xo, yo, wd, ht, oscr, page_x, page_y);
}
else { // create the offscreen
// some platforms seem to need a context to base the offscreen
// on, so make the main window current here...
main_window->make_current();
// set the dimensions for the offscreen surface
os_w = 2000; os_h = 2000;
oscr = fl_create_offscreen(os_w, os_h);
// did the create fail?
if(!oscr) {
// Fail - clear the dimensions out again
os_w = os_h = 0;
}
}
} // draw method
/*****************************************************************************/
int oscr_box::handle(int ev) {
// call the base class event handler
int ret = Fl_Box::handle(ev);
// if there is no offscreen surface, we can return now
if(!oscr) return ret;
// Handle dragging of visible area - if a valid context exists.
// All sorts of editor stuff could be added here... later...
switch(ev) {
case FL_ENTER:
main_window->cursor(FL_CURSOR_MOVE);
ret = 1;
break;
case FL_LEAVE:
main_window->cursor(FL_CURSOR_DEFAULT);
ret = 1;
break;
case FL_PUSH:
x_old = Fl::event_x_root();
y_old = Fl::event_y_root();
drag_state = 1; // drag
ret = 1;
break;
case FL_DRAG:
if(drag_state == 1) { // dragging is active
// how far did we drag since last event?
int x_new = Fl::event_x_root();
int y_new = Fl::event_y_root();
int xoff = x_old - x_new;
int yoff = y_old - y_new;
x_old = x_new;
y_old = y_new;
// update the view position by the drag amount
page_x += xoff;
page_y += yoff;
// check the page bounds and clamp at edges
if(page_x < -w()) page_x = -w();
else if(page_x > os_w) page_x = os_w;
if(page_y < -h()) page_y = -h();
else if(page_y > os_h) page_y = os_h;
// trigger a redraw of the view because we moved
redraw();
}
ret = 1;
break;
case FL_RELEASE:
drag_state = 0; // not dragging any more
ret = 1;
break;
default:
break;
}
return ret;
} // handle
/*****************************************************************************/
static oscr_box *os_box = 0; // a widget to view the offscreen with
/*****************************************************************************/
static void oscr_drawing (void) {
Fl_Color col;
static int icol = 56; // a random colour on the ramp
static int ox = 1000, oy = 1000; // somewhere in the offscreen area
static int iters = 3456; // more than 1024...
if(!oscr) return; // nothing to do here...
fl_begin_offscreen(oscr); /* Open the offscreen context for drawing */
// for the demo, we "reset" the offscreen periodically
if(iters > 1024) {
fl_color(FL_WHITE);
fl_rectf(0, 0, os_w, os_h);
iters = 0;
}
iters++;
// pick a random colour to draw with
icol++; if(icol > 255) icol = 56;
col = (Fl_Color)icol;
fl_color(col); // set the colour
// pick a random position
int rnd = rand();
double drx = (double)os_w * (double)rnd / (double)RAND_MAX;
rnd = rand();
double dry = (double)os_h * (double)rnd / (double)RAND_MAX;
// pick a random line thickness
rnd = rand();
double drt = 4.0 * (double)rnd / (double)RAND_MAX;
// draw a line from the old point to the new end point
int ex = (int)drx;
int ey = (int)dry;
// draws a solid line of thickness drt
fl_line_style(FL_SOLID, (int)drt);
fl_line(ox, oy, ex, ey);
// old point moved to new end point
ox = ex; oy = ey;
fl_end_offscreen(); // close the offscreen context
} // oscr_drawing
/*****************************************************************************/
static void oscr_anim(void *) {
if(oscr) { // offscreen exists, draw something
oscr_drawing();
}
// request a redraw of the view box
os_box->redraw();
// repeat the animation delay
Fl::repeat_timeout(0.1, oscr_anim);
} // oscr_anim
/*****************************************************************************/
int main (int argc, char **argv) {
int win_size = 600;
// create the main window
main_window = new Fl_Double_Window(win_size, win_size, "Offscreen
Demo");
main_window->begin();
// a view of the offscreen, inside the main window
os_box = new oscr_box(5, 5, (win_size - 10), (win_size - 10));
main_window->end();
main_window->resizable(os_box);
// show the app
main_window->show(argc, argv);
// seed the random number sequence
srand(time(NULL));
// add a timer to animate the view updates
Fl::add_timeout(0.1, oscr_anim);
// start the fltk loop
return Fl::run();
} // main
/* end of file */
SELEX Galileo Ltd
Registered Office: Sigma House, Christopher Martin Road, Basildon, Essex SS14
3EL
A company registered in England & Wales. Company no. 02426132
********************************************************************
This email and any attachments are confidential to the intended
recipient and may also be privileged. If you are not the intended
recipient please delete it from your system and notify the sender.
You should not copy it or use it for any purpose nor disclose or
distribute its contents to any other person.
********************************************************************
_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk