Re: How to draw some simple picture?



On Sat, 04 Aug 2007 15:07:01 +0800
"Ye Wenbin" <wenbinye gmail com> wrote:

Hi,
I know that there is a module Gnome2::Canvas, but I'm looking for a way to
draw simple picture using Gtk2, since the Gnome2::Canvas still have no ppm.
I have read the demo script scribble.pl, but I can't learning more from the
example. I don't know how to set up a Gtk2::Gdk::Gc, how to handle
expose event, and so on. Is there more description about Gtk2::DrawingArea?
Thanks!

Hi, I struggled with this myself in the past, and wrote a little
tutorial. Now this works, but it has been criticized for the way
it gets the color from the graphic's context( some wasteful operations). 
To be honest, I just did it the way the drawing area demo did it,
because I couldn't fully understand what it was myself.

The big point though, is to realize that the Drawing Area is not
persistent (the tutorial below shows this) and you need to make an
image to store the area, and it needs to be reloaded constantly,
in the expose event. 

Anyways, see: http://perlmonks.org?node_id=583578
for the code and explanation. Any improvements are welcome.


You may also be interested in this code below
which incorporates rulers with the drawing area. 
Any improvements welcome.

#!/usr/bin/perl
use warnings;
use strict;
use Glib qw/TRUE FALSE/;
use Gtk2 -init;

my $xsize = 2400;
my $ysize = 100;
my %allocated_colors;

# Create the window
my $window = new Gtk2::Window ( "toplevel" );
$window->signal_connect ("delete_event", sub { Gtk2->main_quit; });
$window->set_border_width (10);
$window->set_size_request(500,300);
$window->set_position('center');

my $hbox = Gtk2::HBox->new( 0, 0 );
$window->add($hbox);
$hbox->set_border_width(2);

my $vboxl= Gtk2::VBox->new( 0, 0 );
$hbox->pack_start($vboxl,0,0,0);
$vboxl->set_border_width(2);

my $vboxr= Gtk2::VBox->new( 0, 0 );
$vboxr->set_border_width(2);

my $scwin = Gtk2::ScrolledWindow->new();
my $ha1   = $scwin->get_hadjustment;
$scwin->set_policy('always','never');

$scwin->add_with_viewport($vboxr);

$hbox->pack_start($scwin,1,1,0);

# Create the drawing area.
my $area = new Gtk2::DrawingArea;
$area->size ($xsize, $ysize);
$vboxr->pack_start($area,1,1,0);
$area->set_events (['pointer_motion_mask', 'pointer_motion_hint_mask']);

my $fillarea = new Gtk2::DrawingArea;
$fillarea->size (20, 20);

# The horizontal ruler goes on bottom. As the mouse moves across the
# drawing area, a motion_notify_event event is propagated to the
# ruler so that the ruler can update itself properly.
my $hrule = new Gtk2::HRuler;
$hrule->set_metric ('pixels');
$hrule->set_range (0, 2400, 0, 10);
$area->signal_connect (motion_notify_event => sub { $hrule->event ($_[1]) });
$vboxr->pack_start($hrule,0,0,0); #expand,fill,padding
$hrule->show;

# The vertical ruler goes on the left. As the mouse moves across the
# drawing area, a motion_notify_event event is propagated to the
# ruler so that the ruler can update itself properly.
my $vrule = new Gtk2::VRuler;
$vrule->set_metric ('pixels');
#$vrule->set_range ($ysize,0, 10, $ysize); #$lower, $upper, $position, $max_size
$vrule->set_range ($ysize,0, 0, 10);

$area->signal_connect (motion_notify_event => sub {$vrule->event ($_[1]) });
$vboxl->pack_start($vrule,1,1,0);
$vboxl->pack_end($fillarea,0,0,0);

$window->show_all;

$area->signal_connect(event=>\&cb_da_event);

my $gdkwin = $hrule->window;

#the gdkwindow children are buttons, not the packing boxes 
#the gdk window is the actual paintable surface on the screen,
# the children are areas of different painting, so the packing
#boxes are not gdk children, but the buttons are.
#my @clist = $gdkwin->get_children;
#print "@clist\n";
#my $gdkwindowC = $clist[2];

my ($x0, $y0, $width0, $height0, $depth) = $gdkwin->get_geometry;
print "geometry x0->$x0, y0->$y0, width->$width0, height->$height0, depth->$depth\n";

my ($drawable, $x_offset, $y_offset) = $gdkwin->get_internal_paint_info;
print "drawable->$drawable, x_offset->$x_offset, y_offset->$y_offset\n\n";


Gtk2->main;



########################################################
sub get_color {
    my ($colormap, $name) = @_;
    my $ret;

    if ($ret = $allocated_colors{$name}) {
        return $ret;
    }

    my $color = Gtk2::Gdk::Color->parse($name);
    $colormap->alloc_color($color,TRUE,TRUE);

    $allocated_colors{$name} = $color;

    return $color;
}
##########################################################

sub draw_line {
    my($widget,$line,$color) = @_;
   # see Gdk::Gdk::Window, Gtk2::Gdk::Drawable, Gtk2::Gdk::GC

    my $colormap = $widget->window->get_colormap;

    my $gc = $widget->{gc} || new Gtk2::Gdk::GC $widget->window;
    $gc->set_foreground(get_color($colormap, $color));

    $widget->window->draw_line($gc, @$line);
}

##########################################################
sub draw_poly {
    my($widget,$points,$color) = @_;
   # see Gdk::Gdk::Window, Gtk2::Gdk::Drawable, Gtk2::Gdk::GC

    my $colormap = $widget->window->get_colormap;

    my $gc = $widget->{gc} || new Gtk2::Gdk::GC $widget->window;
    $gc->set_foreground(get_color($colormap, $color));

    $widget->window->draw_polygon($gc,1, @$points);
}

##########################################################
# Draw a line in the expose callback
sub cb_da_event {
    my $this = shift;
    my $event = shift;

    if ($event->type eq "expose") {
        draw_line($this, [30,30, 200,100], "red");
        draw_line($this, [200,30, 30,100], "blue");
        draw_poly($this, [10,10,20,20,10,30],'green');
        
    }
}
############################################################
__END__


zentara
-- 
I'm not really a human, but I play one on earth.
http://zentara.net/japh.html



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]