Show graphs using PyGTK

04Apr11

Although PyGTK is in its final days, I’m still using it on DeTraS development, and I needed a way to generate charts and show them in the GUI. In this post I’ll give you some steps to perform this task easily.

The first step is to find a way to draw charts and graphs. After looking for an easy and lightweight Python module to perform this task, I decided to try with Pycha. It’s really simple to generate a plot using it, so I think you’ll be able to draw a chart just hacking a bit with these examples (included in Pycha’s code).

Example of chart using Pycha and PyGTK

Now, you should paint a chart in your GUI. PyGTK provides a class to perform drawings on the screen, called DrawingArea. The best way to use this class is creating a subclass and implementing some methods to draw and handle some signals. In my case, I wanted to show several types of plots, so I’ve created an abstract class called Plot, which is a subclass of DrawingArea and it’s the parent of LinePlot and VBarPlot classes, which will hold and paint a line chart and a vertical bar chart respectively.

Once you have a class extending DrawingArea, you need to implement two methods to handle expose_event and size-allocate signals. The expose_event signal will be fired every time your DrawingArea is shown or it has to be redrawn. The size-allocate signal will be fired when the window that holds your DrawingArea is resized.

I’m sure you would rather want to see some code instead of reading more boring explanations about what I’ve done. No problem, this is the code of Plot class:

class Plot (gtk.DrawingArea):
    def __init__ (self):
        gtk.DrawingArea.__init__(self)
        self.connect ("expose_event", self.expose)
        self.connect ("size-allocate", self.size_allocate)
        self._surface = None
        self._options = None

    def set_options (self, options):
        """Set plot's options"""
        self._options = options

    def set_data (self, data):
        pass

    def plot (self):
        pass

    def expose (self, widget, event):
        context = widget.window.cairo_create ()
        context.rectangle (event.area.x, event.area.y,
                event.area.width, event.area.height)
        context.clip ()
        self.draw (context)
        return False

    def draw (self, context):
        rect = self.get_allocation()
        self._surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, \
                rect.width, rect.height)
        self.plot ()
        context.set_source_surface (self._surface, 0, 0)
        context.paint ()

    def size_allocate (self, widget, requisition):
        self.queue_draw ()

And these is LinePlot class:

class LinePlot (Plot):
    def __init__ (self):
        Plot.__init__ (self)

    def set_data (self, data):
        """
        Update plot's data and refreshes DrawingArea contents. Data must be a
        list containing a set of x and y values.
        """
        self._data = (('Data', data),)
        self.queue_draw ()

    def plot (self):
        """Initializes chart (if needed), set data and plots."""
        chart = LineChart (self._surface, self._options)
        chart.addDataset (self._data)
        chart.render ()

If you want to see the complete source file, you can find it here.

Nice hacking😉





No Responses Yet to “Show graphs using PyGTK”

  1. Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: