Drawing graphs with GtkDrawingArea
is very easy. This is even easier using Graph_Core.
Some details about Graph_Core
Standard event registration is performed in
Graph_Core constructor.
You don't need to redo it on your own.
Some useful functions are ready for use :
- color setting :
Graph_Core::set_color()
- graphic context :
Graph_Core::gc()
- colormap :
Graph_Core::colormap()
To create some drawings, you need a graphic context
and colors setting. All other drawing primitives are available
as GdkDrawable methods.
Class usage
Making some rotating graphs like vu-meters is very easy with
the Grapher class.
- note 1 - create a Grapher class,
- note 2 - data acquisition done in a timeout handler,
- note 3 - this is a rotating graph, so translate it by one
pixel
- note 4 - generate some pseudo-data
- note 5 - plot this data (in percentile or absolute units).
- note 6 - refresh graph every 10 ms.
<?php
$grapher = new Grapher(); // note 1
$grapher->set_size_request(300, 200);
$window = new GtkWindow();
$window->connect_simple('destroy', array('gtk', 'main_quit'));
$window->set_title('Graph demo');
$window->set_position(Gtk::WIN_POS_CENTER);
$window->set_border_width(8);
$window->add($grapher);
$window->show_all();
Gtk::timeout_add(100, 'graph_timeout', $grapher); // note 2
Gtk::main();
/**
* an arbitrary function generator.
*
*/
function graph_timeout($graph) {
static $value = 0;
static $delta = 1;
static $count = 0;
if (!$graph->realized())
return true;
if ($count > 1)
$graph->translate(); // note 3
$count++;
if ($value>100 || $value < 0)
$delta *= -1;
$value += $delta;
$sin = intval(100 * sin($count * 3.14 / 180)); // note 4
$cos = intval(100 * cos($count * 3.14 / 180));
$graph->plot(0+$value, 'blue', $mode_percent=true); // note 5
$graph->plot($sin, 'red' , $mode_percent=false);
$graph->plot($cos, 'green', $mode_percent=false);
Gtk::timeout_add(10, 'graph_timeout', $graph); // note 6
return false;
}
?>
Class source
This class is provided in two parts :
Graph_Core contains basic functions
that may be reusable for other projects,
Grapher class contains basic functions to
generate a rotating graph.
Class Graph_core
<?php
class Graph_Core extends GtkDrawingArea {
# prefix class attributes with "_" to avoid collisions
# with GtkDrawingArea attributes.
protected $_pixmap;
protected $_gc;
protected $_realized;
function __construct() {
parent::__construct();
$this->connect('expose_event',
array($this, 'expose_event'));
$this->connect('configure_event',
array($this, 'configure_event'));
$this->connect('realize',
array($this, 'realize'));
$this->set_events(Gdk::EXPOSURE_MASK
| Gdk::LEAVE_NOTIFY_MASK);
$this->_pixmap = null;
$this->_gc = null;
$this->_realized = false;
}
function realize() {
$this->_realized = true;
}
function realized() {
return $this->_realized;
}
function configure_event($widget, $event) {
$w = $this->width();
$h = $this->height();
# allocate a new pixmap of the requested size ($this->allocation)
$this->_pixmap = new GdkPixmap($this->window, $w, $h, -1);
# clear pixmap (white color)
$this->_pixmap->draw_rectangle($this->style->white_gc, true,
0, 0, $w, $h);
return true;
}
function expose_event($widget, $event) {
$this->window->draw_drawable($this->style->fg_gc[$this->state],
$this->pixmap(),
$event->area->x, $event->area->y,
$event->area->x, $event->area->y,
$event->area->width, $event->area->height
);
return false;
}
function set_color($color) {
$col = $this->colormap()->alloc_color($color);
if ($col === false)
return $this->foreground('black');
return $this->gc()->set_foreground($col);
}
function colormap() {
return $this->gc()->get_colormap();
}
function pixmap() {
if (!$this->realized()) {
trigger_error("Widget not realized ; can't get pixmap");
return null;
}
return $this->_pixmap;
}
function gc() {
if (!$this->realized()) {
trigger_error("Widget not realized ; can't get GC");
return null;
}
if ($this->_gc == null)
$this->_gc = new GdkGc($this->pixmap());
return $this->_gc;
}
function width() {
return $this->allocation->width;
}
function height() {
return $this->allocation->height;
}
function w() {
return $this->width();
}
function h() {
return $this->height();
}
}
// file continues with class grapher
?>
class Grapher
<?php
// continuation of previous code piece
class Grapher extends Graph_Core{
/**
* plot a dot to the pixmap
*/
function plot ($value, $color = 'black', $mode_percent = false,
$x=null, $plot_w=1) {
$this->set_color($color);
if ($x == null)
$x = $this->w()-1;
if ($mode_percent) {
# $value is in percent
$value = $value * $this->h() / 100;
$y = intval($this->h() - $value);
} else {
# 0 is in middle of window
$y = $this->h() / 2 - $value;
}
if ($plot_w == 1) {
$this->pixmap()->draw_point($this->gc(), $x, $y);
$this->queue_draw_area($x, $y, 1, 1);
} else {
$this->pixmap()->draw_arc($this->gc(), true,
$x - $plot_w, $y - $plot_w, $plot_w*2, $w*2,
0, 64 * 360);
$this->queue_draw_area($x - $w, $y - $plot_w,
$plot_w*2, $plot_w*2);
}
}
/**
* scroll pixmap
*/
function translate($dx = -1, $dy = 0) {
$w = $this->w();
$h = $this->h();
# get full pixmap content into $img
$img = $this->pixmap()->get_image(0, 0, $w, $h);
# clear full area
$this->pixmap()->draw_rectangle($this->style->white_gc, true,
0, 0, $w, $h);
# draw $img with delta (translation)
$this->pixmap()->draw_image($this->gc(), $img, 0, 0,
$dx, $dy, $w, $h);
$this->queue_draw_area(0,0, $w, $h);
}
}
?>
Links
Recent comments
6 weeks 2 days ago
12 weeks 1 day ago
13 weeks 6 days ago
20 weeks 2 days ago
21 weeks 4 days ago
21 weeks 6 days ago
22 weeks 6 days ago
23 weeks 5 days ago
34 weeks 4 days ago
34 weeks 4 days ago