Fl_Chart in FLUID

185 views
Skip to first unread message

David Topham

unread,
Jul 19, 2013, 5:34:19 PM7/19/13
to fltkg...@googlegroups.com
I am trying to use Fl_Chart and found this example (by Greg Ercolano (without whom we would all still be using stone tablets!))

#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Chart.H>
#include <math.h>
// Demonstration of how to use Fl_Chart -- erco 11/20/08
int main() {
    Fl_Window *win = new Fl_Window(1000, 480);
    Fl_Chart  *chart = new Fl_Chart(20, 20, win->w()-40, win->h()-40, "Chart");
    chart->bounds(-125.0, 125.0);
    chart->type(FL_LINE_CHART);
    for ( double t=0; t<15; t+=0.5 ) {
        double val = sin(t) * 125.0;
        static char val_str[20];
        sprintf(val_str, "%.0lf", val);
        chart->add(val, val_str, (val<0)?FL_RED:FL_GREEN);
    }
    win->resizable(win);
    win->show();
    return(Fl::run());
}

Works great, by I can't figure out how to add this to my FLUID project.  I think subclassing may be the answer, but subclass what?
I tried subclassing Fl_Chart, but then I get error that "error: 'end' was not declared in this scope"

I would appreciate any suggestions even if just generally how to add new controls to FLUID.

What I really am aiming for is to have a second window with tabs and have the chart show up in one of the tab "groups"
I am able to get a line drawn using fl_line that way, but the Fl_chart never shows up no matter how I use redraw and do_callback, etc.

-Dave

Greg Ercolano

unread,
Jul 19, 2013, 6:02:10 PM7/19/13
to fltkg...@googlegroups.com
On 07/19/13 14:34, David Topham wrote:
> I am trying to use Fl_Chart ..
> how to add this to my FLUID project [..]

The easiest thing to do, I think use a box in place of the chart
inside fluid, and then change the 'Class:' property for the box to Fl_Chart. eg:

1) New -> Other -> Box
2) Size/position the box where you want the chart to be
3) Open the "Properties" for the box
4) Under the C++ tab, set Class: Fl_Chart

Add your own #include <FL/Fl_Chart.H>, so that your fluid generated code
includes the definition for Fl_Chart. You can do that using New->Code->Declaration.

David Topham

unread,
Jul 20, 2013, 7:22:53 PM7/20/13
to fltkg...@googlegroups.com, erco_...@seriss.com
I did all that (I believe), but still the chart does not display. I expect it is related to the "callback"? Perhaps it is never getting called? How could I force that?  (attached is the fl and cxx files)
try_chart.cxx
try_chart.fl
try_chart.h

Greg Ercolano

unread,
Jul 20, 2013, 11:36:10 PM7/20/13
to fltkg...@googlegroups.com
On 07/20/13 16:22, David Topham wrote:
> I did all that (I believe), but still the chart does not display.

The widget /is/ being displayed, but there's no data being
assigned to the chart because you appear to have implemented
the initialization code as a callback, instead of in main().

Not all widgets use callbacks.. callbacks are usually invoked
when someone interacts with the widget, like pushing a button
on a button widget, or typing text into a text widget.

Fl_Chart is not really a widget one interacts with.. it's a
display-only widget, so in your case it seems like you want
the chart data to be assigned to the widget as soon as the
widget is created.

Since you have the widget being created in main(), you'll
want to assign the data to the chart in main() as well.

I would suggest take out all the code you've put into the Callback:
window, and instead put it into a New -> Code -> Code window attached
to main(), so that it's assigned to the widget right after the widget
is created.

To do that:

1) Click on the chart widget, open the properties, and under C++ -> Name:
type 'mychart'

2) Click on 'main()' in fluid, and choose: New -> Code -> Code
3) In the code dialog window, paste the chart initialization code,
referring to the chart widget as 'mychart'

mychart->bounds(-125.0, 125.0);
for ( double t=0; t<15; t+=0.5 )
{
double val = sin(t) * 125.0;
static char val_str[20];
sprintf(val_str, "%.0lf", val);
mychart->add(val, val_str, (val<0)?FL_RED:FL_GREEN);
}


Here's the chart.fl file that does this:

------------------------------------------------------ chart.fl

# data file for the Fltk User Interface Designer (fluid)
version 1.0300
header_name {.h}
code_name {.cxx}
decl {\#include <FL/Fl_Chart.H>} {public global
}

decl {\#include <math.h>} {selected private local
}

Function {} {open
} {
Fl_Window {} {
label {Chart Demo}
xywh {623 21 355 275} type Double visible
} {
Fl_Box mychart {
label Chart
xywh {25 25 305 222} align 5
class Fl_Chart
}
}
code {mychart->bounds(-125.0, 125.0);
for ( double t=0; t<15; t+=0.5 )
{
double val = sin(t) * 125.0;
static char val_str[20];
sprintf(val_str, "%.0lf", val);
mychart->add(val, val_str, (val<0)?FL_RED:FL_GREEN);
}} {}
}

------------------------------------------------------ end

-- OR --

If you want, you can put the initialization code into a function instead,
and call the function within the chart's 'Extra Code'.

So /instead/ of doing the above, using New->Code->Code being part of main(),
you would undo that mod, and do this instead:

1) Click above main() (ie. on one of your #includes)
2) Create a new function called InitializeChart():

2a) Choose: New -> Function/Method
..and fill out the form:
Name(args): InitializeChart(Fl_Chart *chart)
Return Type: void
..so that the chart widget is passed in as an argument called 'chart'.

2b) Assign code to the function:
New -> Code -> Code
..and in the code window dialog, paste the following (slightly different) code:

chart->bounds(-125.0, 125.0);
for ( double t=0; t<15; t+=0.5 )
{
double val = sin(t) * 125.0;
static char val_str[20];
sprintf(val_str, "%.0lf", val);
chart->add(val, val_str, (val<0)?FL_RED:FL_GREEN);
}

Note here, I'm referring to the chart as the argument to the function,
not the 'mychart' global name you assigned to the chart. This allows the
function to work with /any/ chart, not just the global one.

3) Call this new function from your chart widget's Extra Code:

3a) Click on your 'Fl_Chart' widget in fluid
3b) Open "Properties"
3c) Under C++ -> Extra Code:, type:
InitializeChart(mychart);

Now when the chart widget is created, it calls your new function InitializeChart()
as part of the widget's initialization, passing the instance 'mychart' as the argument
to your function, and the function will fill that instance of the chart with the data.

Functionally the same as my first suggestion above, but a bit more flexible
because you can use that function on /any/ instance of an Fl_Chart, not just
the global 'mychart' instance. Also, this let's you call the initialization
from something like a button callback or timer.

Here's a copy of the above as an .fl file:

------------------------------------------------------ chart2.fl

# data file for the Fltk User Interface Designer (fluid)
version 1.0300
header_name {.h}
code_name {.cxx}
decl {\#include <FL/Fl_Chart.H>} {public global
}

decl {\#include <math.h>} {private local
}

Function {InitializeChart(Fl_Chart *chart)} {
comment {A FUNCTION TO INITIALIZE AN Fl_Chart} open
} {
code {chart->bounds(-125.0, 125.0);
for ( double t=0; t<15; t+=0.5 )
{
double val = sin(t) * 125.0;
static char val_str[20];
sprintf(val_str, "%.0lf", val);
chart->add(val, val_str, (val<0)?FL_RED:FL_GREEN);
}} {}
}

Function {} {open
} {
Fl_Window {} {
label {Chart Demo} open
xywh {623 21 355 275} type Double visible
} {
Fl_Box mychart {
label Chart selected
xywh {25 25 305 222} align 5
code0 {InitializeChart(mychart);}
class Fl_Chart
}
}
}

------------------------------------------------------ end

David Topham

unread,
Jul 21, 2013, 12:08:57 AM7/21/13
to fltkg...@googlegroups.com
Greg, That works perfectly!  You are not only generous with your time, but an excellent teacher as well since I understand your explanation and the way callbacks work much better.  It does make me curious why FLUID would have a Textbox to enter callbacks for Fl_Box if they would not be invoked, but I imagine there is some reason; perhaps for consistency of the interface. I am really enjoying FLTK/FLUID for developing programs.  -Dave


--
You received this message because you are subscribed to a topic in the Google Groups "fltk.general" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/fltkgeneral/vUyBIvhD2w0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to fltkgeneral...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



Greg Ercolano

unread,
Jul 21, 2013, 12:15:45 AM7/21/13
to fltkg...@googlegroups.com
On 07/20/13 21:08, David Topham wrote:
> Greg, That works perfectly! You are not only generous with your time, but an excellent teacher as well since I understand your explanation and the way callbacks work much better.

Cool, ya I should do more of those videos.. "someday"

> It does make me curious why FLUID would have a Textbox to enter callbacks for Fl_Box if they would not be invoked, but I imagine there is some reason; perhaps for consistency of the interface. I am really enjoying FLTK/FLUID for developing programs. -Dave

You'll know the minute you need it ;)

I can think of a lot of reasons; say you had a custom widget that wasn't
that used a callback, and you wanted to use an Fl_Box to stand in for it
in fluid using the same Class: method we used to allow it to stand in for Fl_Chart,
but also wanted to manipulate that widget's callback from within fluid.

Also: all FLTK widgets derive from Fl_Widget in the end, and Fl_Widget
supports callbacks (whether the widget uses them or not). This is so that
even a simple widget (like Fl_Box that doesn't use a callback) can be
extended/subclassed into one that does.




Reply all
Reply to author
Forward
0 new messages