14

I want to be able to make a line graph using GTK+ but I'm unsure how to approach this. Has anyone got any hints or tips?

liberforce
  • 11,189
  • 37
  • 48
paultop6
  • 3,691
  • 4
  • 29
  • 37

3 Answers3

13

Edit:

Here are GTK+ 2 and GTK+ 3 versions of that program:

Original answer:

Here's a GTK2 application using cairo to draw a simple math function:

#include <gtk/gtk.h>
#include <math.h>
#include <cairo.h>

#define WIDTH   640
#define HEIGHT  480

#define ZOOM_X  100.0
#define ZOOM_Y  100.0


gfloat f (gfloat x)
{
    return 0.03 * pow (x, 3);
}

static gboolean
on_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
{
    cairo_t *cr = gdk_cairo_create (widget->window);
    GdkRectangle da;            /* GtkDrawingArea size */
    gdouble dx = 5.0, dy = 5.0; /* Pixels between each point */
    gdouble i, clip_x1 = 0.0, clip_y1 = 0.0, clip_x2 = 0.0, clip_y2 = 0.0;
    gint unused = 0;

    /* Define a clipping zone to improve performance */
    cairo_rectangle (cr, 
            event->area.x, 
            event->area.y, 
            event->area.width, 
            event->area.height);
    cairo_clip (cr);

    /* Determine GtkDrawingArea dimensions */
    gdk_window_get_geometry (widget->window, 
            &da.x, 
            &da.y, 
            &da.width, 
            &da.height, 
            &unused);

    /* Draw on a black background */
    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
    cairo_paint (cr);

    /* Change the transformation matrix */
    cairo_translate (cr, da.width / 2, da.height / 2);
    cairo_scale (cr, ZOOM_X, -ZOOM_Y);  

    /* Determine the data points to calculate (ie. those in the clipping zone */
    cairo_device_to_user_distance (cr, &dx, &dy);
    cairo_clip_extents (cr, &clip_x1, &clip_y1, &clip_x2, &clip_y2);
    cairo_set_line_width (cr, dx);

    /* Draws x and y axis */
    cairo_set_source_rgb (cr, 0.0, 1.0, 0.0);
    cairo_move_to (cr, clip_x1, 0.0);
    cairo_line_to (cr, clip_x2, 0.0);
    cairo_move_to (cr, 0.0, clip_y1);
    cairo_line_to (cr, 0.0, clip_y2);
    cairo_stroke (cr);

    /* Link each data point */
    for (i = clip_x1; i < clip_x2; i += dx)
        cairo_line_to (cr, i, f (i));

    /* Draw the curve */
    cairo_set_source_rgba (cr, 1, 0.2, 0.2, 0.6);
    cairo_stroke (cr);

    cairo_destroy (cr);
    return FALSE;
}


int
main (int argc, char **argv)
{
    GtkWidget *window;
    GtkWidget *da;

    gtk_init (&argc, &argv);

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size (GTK_WINDOW (window), WIDTH, HEIGHT);
    gtk_window_set_title (GTK_WINDOW (window), "Graph drawing");
    g_signal_connect (G_OBJECT (window), "destroy", gtk_main_quit, NULL);

    da = gtk_drawing_area_new ();
    gtk_container_add (GTK_CONTAINER (window), da);

    g_signal_connect (G_OBJECT (da), 
            "expose-event", 
            G_CALLBACK (on_expose_event), 
            NULL);

    gtk_widget_show_all (window);
    gtk_main ();

    return 0;
}
liberforce
  • 11,189
  • 37
  • 48
10

I just want to add some more alternatives to this common request.

  1. libgoffice
    This is the library used by Gnumeric and AbiWord, so it is actively maintained and fairly stable: one of the sanest alternative currently available. Unfortunately, there is no official home page and it lacks beginners documentation.
  2. GtkDatabox
    It recently changed the maintainer, so there is some uncertainty in the future. It used to be a good solution for rendering a lot of data in line plots.
  3. GtkExtra2
    This was the old de-facto standard of plotting charts in GTK+. The jump to GTK+2 seems to have been fatal to this project.
  4. GTK+ instrumentation widgets and GLineGraph
    Somewhat spartans but good for simple stuff.

Other than that, a lot of projects implement internally some kind of GTK+ charting. Other than the yet cited Gnuplot, there is also Gwyddion and gretl. And I'm pretty sure I'm missing tons of others.

In conclusion, there is no general consensus nor a de-facto standard for charting in the GTK+ world...

ntd
  • 7,372
  • 1
  • 27
  • 44
  • 3
    Im currently having a look at how gnome-system-monitor draws its graphs, to me the way it implements it using cairo seems to be a good way to plot, plus im trying to plot in real time as well. Thanks for you info ntd, its all taken on board. – paultop6 Apr 13 '10 at 17:31
2

Have a look at the gnuplot there are some C++ libraries that interface with gnuplot, which do what you are looking for and then some. It is very easy to use if you've ever used gnuplot.

hhafez
  • 38,949
  • 39
  • 113
  • 143
  • 6
    Faced with the same question as the OP 5.5 years ago, I wonder why this answer was accepted? It does not answer the question! At the very least, a one-sentence-hint how the plot (created with gnuplot) could be displayed in a Gtk widget is missing. – Ludwig Schulze Dec 20 '15 at 21:11