FL_Table - example?

1,197 views
Skip to first unread message

domonic Thomson

unread,
Jul 25, 2013, 5:04:00 AM7/25/13
to fltkg...@googlegroups.com
I'm desperately trying to understand the FL_Table widget and have been studying the Simple Table example provided with FLTK 1.3.2.

I've been trying to understand how the Switch statement works and think I've figured it out.  It will reveal my substandard level of competency but I'm literally going to be here forever if I don't ask.

Below is the MyTable Class derived from FL_Table.

At the bottom of this class is the constructor for MyTable.  
When the line in the constructor reaches  row_header(1) and col_header(1) and the fact that these functions return a 'context flag' such as 
CONTEXT_ROW_HEADER and CONTEXT_COL_HEADER respectively do these functions row_header() and col_header() call the draw_cell function and pass it the context flag which is then utilized in the switch statement (see below)?

That is my interpretation of it.  I'm not asking for a granular appraisal of my perspective but I do want to know if I am on the right track.

My confusion with this has been with how this switch statement is used and the above explanation is my interpretation of how it is used.   
Thanks once again. 
I'm really loving FLTK by the way. Learning something new everyday.




class MyTable : public Fl_Table {


 
int data[MAX_ROWS][MAX_COLS]; // data array for cells


 
// Draw the row/col headings
 
//    Make this a dark thin upbox with the text inside.
 
//
 
void DrawHeader(const char *s, int X, int Y, int W, int H) {
    fl_push_clip
(X,Y,W,H);
      fl_draw_box
(FL_THIN_UP_BOX, X,Y,W,H, row_header_color());
      fl_color
(FL_BLACK);
      fl_draw
(s, X,Y,W,H, FL_ALIGN_CENTER);
    fl_pop_clip
();
 
}
 
// Draw the cell data
 
//    Dark gray text on white background with subtle border
 
//
 
void DrawData(const char *s, int X, int Y, int W, int H) {
    fl_push_clip
(X,Y,W,H);
     
// Draw cell bg
      fl_color
(FL_WHITE); fl_rectf(X,Y,W,H);
     
// Draw cell data
      fl_color
(FL_GRAY0); fl_draw(s, X,Y,W,H, FL_ALIGN_CENTER);
     
// Draw box border
      fl_color
(color()); fl_rect(X,Y,W,H);
    fl_pop_clip
();
 
}
 
// Handle drawing table's cells
 
//     Fl_Table calls this function to draw each visible cell in the table.
 
//     It's up to us to use FLTK's drawing functions to draw the cells the way we want.
 
//
 
void draw_cell(TableContext context, int ROW=0, int COL=0, int X=0, int Y=0, int W=0, int H=0) {
   
static char s[40];
   
switch ( context ) {
     
case CONTEXT_STARTPAGE:                   // before page is drawn..
        fl_font
(FL_HELVETICA, 16);              // set the font for our drawing operations
       
return;
     
case CONTEXT_COL_HEADER:                  // Draw column headers
        sprintf
(s,"%c",'A'+COL);                // "A", "B", "C", etc.
       
DrawHeader(s,X,Y,W,H);
       
return;
     
case CONTEXT_ROW_HEADER:                  // Draw row headers
        sprintf
(s,"%03d:",ROW);                 // "001:", "002:", etc
       
DrawHeader(s,X,Y,W,H);
       
return;
     
case CONTEXT_CELL:                        // Draw data in cells
        sprintf
(s,"%d",data[ROW][COL]);
       
DrawData(s,X,Y,W,H);
       
return;
     
default:
       
return;
   
}
 
}
public:
 
// Constructor
 
//     Make our data array, and initialize the table options.
 
//
 
MyTable(int X, int Y, int W, int H, const char *L=0) : Fl_Table(X,Y,W,H,L) {
   
// Fill data array
   
for ( int r=0; r<MAX_ROWS; r++ )
     
for ( int c=0; c<MAX_COLS; c++ )
        data
[r][c] = 1000+(r*1000)+c;
   
// Rows
    rows
(MAX_ROWS);             // how many rows
    row_header
(1);              // enable row headers (along left)
    row_height_all
(20);         // default height of rows
    row_resize
(0);              // disable row resizing
   
// Cols
    cols
(MAX_COLS);             // how many columns
    col_header
(1);              // enable column headers (along top)
    col_width_all
(80);          // default width of columns
    col_resize
(1);              // enable column resizing
   
end(); // end the Fl_Table group
 
}
 
~MyTable() { }
};

Greg Ercolano

unread,
Jul 25, 2013, 12:35:47 PM7/25/13
to fltkg...@googlegroups.com
On 07/25/13 02:04, domonic Thomson wrote:
> Below is the MyTable Class derived from FL_Table.
> At the bottom of this class is the *constructor for MyTable*.

Right, which is this:

MyTable(intX,intY,intW,intH,constchar*L=0):Fl_Table(X,Y,W,H,L){
// Fill data array
for(intr=0;r<MAX_ROWS;r++)
for(intc=0;c<MAX_COLS;c++)
data[r][c]=1000+(r*1000)+c;
// Rows
rows(MAX_ROWS); // how many rows
row_header(1); // enable row headers (along left)
row_height_all(20); // default height of rows
row_resize(0); // disable row resizing
// Cols
cols(MAX_COLS); // how many columns
col_header(1); // enable column headers (along top)
col_width_all(80); // default width of columns
col_resize(1); // enable column resizing
end();// end the Fl_Table group
}

> When the line in the constructor reaches *row_header(1) *and *col_header(1**)*
> and the fact that these functions return a 'context flag'

..hmm, no, those two methods don't return anything;
they just set a flag telling the table what you want headers displayed
for the rows and columns.

The argument to those methods is either 0 or 1;
0 disables headers from appearing in the table,
1 enables headers to appear in the table.

Docs for those methods are here:

void row_header(int):
http://www.fltk.org/doc-1.3/classFl__Table.html#ad51f00bbee634d5ba3c90c67a7c5650a

void col_header(int):
http://www.fltk.org/doc-1.3/classFl__Table.html#abcfb0374426baff30a91aca68dc0aea9

So these are just initialization methods; they tell the table what
features you want (on or off in this case).

What happens is, later, when the table is being drawn (see my previous post
describing how Fl_Table works), since you've enabled headers with those calls,
the table will call your draw_cell() method with 'context' set to CONTEXT_ROW_HEADER
when it wants you to draw the cells in the row header, and set to CONTEXT_COL_HEADER
when it wants you to draw the cells in the column header.

Keep in mind the draw_cell() method is code you supply to draw all
the cells in the table. The arguments passed to draw_cell() tell you
which cell to draw ('row'/'col' args), where the cell is to be drawn on the screen
(x/y/w/h args), and whether it's a row header cell, column header cell, or just a
regular data cell ('context' arg).

> CONTEXT_ROW_HEADER and CONTEXT_COL_HEADER respectively do these functions
> row_header() and col_header() call the draw_cell function and pass it the
> context flag which is then utilized in the switch statement (see below)?

No, row_header() and col_header() just set flags, they don't turn around
and invoke the draw_cell() method.

The draw_cell() method is automatically invoked by FLTK when the table
needs to be redrawn, such as if you unhide the window, or scroll the table,
revealing new cells of data.

> That is my interpretation of it. I'm not asking for a granular appraisal
> of my perspective

Sorry, I did ;)

> but I do want to know if I am on the right track.

Not quite on the right track, but hopefully the above will get you there.

Fl_Table is an unusual widget because the drawing code is actually
handled by you. Most widgets handle all drawing for you.

The reason for this is tables can be large, so the philosophy here
is it's better to let you, the app programmer, have control over
managing the memory of your (potentially huge) cell data, and how
to draw it (either with simple draw code, or more complex code that
handles user interaction like with an Fl_Input).


domonic Thomson

unread,
Jul 25, 2013, 10:38:55 PM7/25/13
to fltkg...@googlegroups.com, erco_...@seriss.com
Thanks for the explanation.  That pretty much covers it. 

Greg Ercolano

unread,
Jul 26, 2013, 1:50:19 AM7/26/13
to fltkg...@googlegroups.com
On 07/25/13 19:38, domonic Thomson wrote:
> Thanks for the explanation. That pretty much covers it.

I guess I should work some of this into the Fl_Table docs..

Message has been deleted

Greg Ercolano

unread,
Oct 10, 2013, 7:47:53 PM10/10/13
to fltkg...@googlegroups.com
On 10/09/13 23:39, Karol Woytila Halauw wrote:
> help. i am a little bit confused about how to instal FL_table especially part windows builds.
> can you give more detail. ? i use OS windows and visual studio 2008 as my compiler thanx.
>
> i tried but the result show like this :
> 1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall Fl_Table::Fl_Table(int,int,int,int,char const *)" (??0Fl_Table@@QAE@HHHHPBD@Z) referenced in function "void __cdecl `dynamic initializer for 'mn3''(void)" (??__Emn3@@YAXXZ)
> 1>...\Visual Studio 2008\Projects\apps\Debug\apps.exe : fatal error LNK1120: 1 unresolved externals

Can we see:

1) Your source code
2) Your compile and link command lines from VS 2008 (ie. build logs)


MacArthur, Ian (Selex ES, UK)

unread,
Oct 11, 2013, 4:56:54 AM10/11/13
to fltkg...@googlegroups.com

> help. i am a little bit confused about how to instal
> FL_table especially part windows builds.
> can you give more detail. ? i use OS windows and
> visual studio 2008 as my compiler thanx.


There are several worked examples in the "examples" folder of the standard tarball, have you studied them to see how they are used? I assume they do work for you when you compile them.


Selex ES 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.
********************************************************************

Greg Ercolano

unread,
Oct 11, 2013, 12:49:26 PM10/11/13
to fltkg...@googlegroups.com
Also:
3) What version of FLTK are you using?
Fl_Table comes with fltk 1.3.x, e.g. fltk 1.3.2 (latest release)

Want to make sure you're not using some much older version
(like 1.1.x) that doesn't have Fl_Table.

Karol Woytila Halauw

unread,
Oct 11, 2013, 1:19:15 PM10/11/13
to fltkg...@googlegroups.com, erco_...@seriss.com

i already did it.
that's so simple in visual studio but it takes a day for me to figure it out, just add existing HEADER FILES (FL.Table.H) & RESOURCE FILES (FL.Table.cxx).

now, i have another problem with this table.
from the picture, i made 25rows & 2coloumns. how to insert data into cell and show it ?
i read i must use draw_cell, but the code is too long,. i just need a simple one only to show.
for example '1 1' for  1st coloumns and 1st row.

Greg Ercolano

unread,
Oct 11, 2013, 4:48:34 PM10/11/13
to fltkg...@googlegroups.com
On 10/11/13 10:19, Karol Woytila Halauw wrote:
> <https://lh6.googleusercontent.com/-36CMFqFFLd4/UlgyIZcQ_BI/AAAAAAAAABM/kj6zWph-iuM/s1600/helpTable.jpg>
Please show your code; it's hard to guess.
Or at least tell us what example code you're starting with.

Fl_Table does not itself manage data; it's up to your app
to provide the data (usually as arrays), and it calls
your draw_cell() code to handle displaying it.

Look at the examples/table-simple.cxx code which uses a
two dimensional integer array called "data". So this example
shows how to manage integer data as an array.

If, using that example, you want to manage only 2 rows and 2 columns
of integer data, you'd fill out the array:

data[0][0] = 123; // row 0 col 0
data[0][1] = 456; // row 0 col 1
data[1][0] = 789; // row 1 col 0
data[1][1] = 999; // row 1 col 1

..then you'd tell Fl_Table there are two rows and two columns:

table.rows(2);
table.cols(2);

When Fl_Table redraws, it will call your draw_cell() method
to draw the data, telling you which row/col it wants you to draw,
and where to draw it (x/y/w/h values), which is a single cell
in the table.

It will call that draw_cell() method for every visible cell
in the table, so that your drawing code handles drawing the
data for each visible cell.

It is up to your code to get the appropriate data from your
array for the specified row + column, and draw it in that
little square it gives you (xywh).

The minimum amount of code would be to turn data[row][col]
into a string, and draw that string (fl_draw()) using a font
(set with fl_font()) and color (set with fl_color())
in the little xywh area it tells you.

See the example for info on how to do that, but it basically
comes down to:

char s[40];
sprintf(s, "%d", data[ROW][COL]); // convert data for this cell to a string
fl_color(FL_WHITE); // pick a white color
fl_rectf(X,Y,W,H); // draw the background of the cell (white)
fl_color(FL_GRAY0); // pick a gray color
fl_draw(s, X,Y,W,H, FL_ALIGN_CENTER); // draw the string (gray) centered in the cell


..where ROW,COL and X,Y,W,H are passed to you from Fl_Table.


Karol Woytila Halauw

unread,
Oct 11, 2013, 9:00:54 PM10/11/13
to fltkg...@googlegroups.com, erco_...@seriss.com
here is my source code.

int main(int argc, char **argv)
{
       win->begin();
        Fl_Window *win = new Fl_Window(400,400);
        Fl_Table *mn3 = new Fl_Table(50,100,300,280,"TABEL NILAI");
        mn3->cols(3);
       
        mn3->rows(26);
        //mn3->draw_cell("11",10,10,10,100,10,10); // it show error "error C2664: 'Fl_Table::draw_cell' : cannot convert parameter 1 from 'const char [3]' to
                                                                       // 'Fl_Table::TableContext'"
       fl_draw("11", 10,10,10,10, FL_ALIGN_CENTER);  // the error will be shown in picture
       win->end();
       win->show();
   
       return(Fl::run());
}


i don't know what function i should use, every function i try but always error.


error.jpg

Greg Ercolano

unread,
Oct 12, 2013, 3:32:13 PM10/12/13
to fltkg...@googlegroups.com
On 10/11/13 18:00, Karol Woytila Halauw wrote:
> here is my source code.
>
> int main(int argc, char **argv)
> {
> win->begin();
> Fl_Window *win = new Fl_Window(400,400);
> Fl_Table *mn3 = new Fl_Table(50,100,300,280,"TABEL NILAI");
> mn3->cols(3);
>
> mn3->rows(26);
> //mn3->draw_cell("11",10,10,10,100,10,10); // it show error "error C2664: 'Fl_Table::draw_cell' : cannot convert parameter 1 from 'const char [3]' to
> // 'Fl_Table::TableContext'"
> fl_draw("11", 10,10,10,10, FL_ALIGN_CENTER); // the error will be shown in picture
> win->end();
> win->show();
>
> return(Fl::run());
> }

No, that's using it wrong; Fl_Table is not like an Fl_Button
where you can just make instances and add a few lines to make
the widget appear.

Fl_Table is different; you have to subclass it, and well,
as the docs say: http://www.fltk.org/doc-1.3/classFl__Table.html#details

"To be useful it must be subclassed and several virtual functions defined.
Normally applications use widgets derived from this widget, and do not use
this widget directly; this widget is usually too low level to be used
directly by applications."

Please refer to the table-simple.cxx example that is in the fltk
examples directory for an example of how to use Fl_Table.

You haven't mentioned what version of FLTK you're using,
so I'll include a copy of the most recent table-simple.cxx
example here, so we know what you're starting with.

Refer to the docs above for a description of the methods
used in this example to figure out how it works. Along with
the comments in the example. and my description in my last post,
it should make sense.
_________________________________________________________________________

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Table.H>
#include <FL/fl_draw.H>

#define MAX_ROWS 30
#define MAX_COLS 26 // A-Z

// Derive a class from Fl_Table
MyTable(int X, int Y, int W, int H, const char *L=0) : Fl_Table(X,Y,W,H,L) {
// Fill data array
for ( int r=0; r<MAX_ROWS; r++ )
for ( int c=0; c<MAX_COLS; c++ )
data[r][c] = 1000+(r*1000)+c;
// Rows
rows(MAX_ROWS); // how many rows
row_header(1); // enable row headers (along left)
row_height_all(20); // default height of rows
row_resize(0); // disable row resizing
// Cols
cols(MAX_COLS); // how many columns
col_header(1); // enable column headers (along top)
col_width_all(80); // default width of columns
col_resize(1); // enable column resizing
end(); // end the Fl_Table group
}
~MyTable() { }
};

int main(int argc, char **argv) {
Fl_Double_Window win(900, 400, "Simple Table");
MyTable table(10,10,880,380);
win.end();
win.resizable(table);
win.show(argc,argv);
return(Fl::run());
}
_____________________________________________________________________________


Reply all
Reply to author
Forward
0 new messages