http://www.perlmonks.org?node_id=1200812

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to draw a coloured bar inside a Gtk2::Frame.

The bar is drawn on a Gnome2::Canvas, contained within the frame. The bar should be as long as possible, but a fixed height. The bar should also be exactly in the middle of the frame.

My problem is that I can't find the size of the Gtk2::Frame that's actually drawn, therefore I can't set the size of the Gnome2::Canvas that would fill it, therefore I can't draw the coloured bar in the right place.

The example script draws a red bar whose width isn't long enough, and whose vertical position is slightly off of centre.

(The call to Gnome2::Canvas->get_size() just returns default values of 100x100, which is not related to the frame's actual size.)

#!/usr/bin/perl use strict; use diagnostics; use warnings; use Gtk2 '-init'; use Glib qw(TRUE FALSE); use Gnome2::Canvas; # Draw a Gtk2 window my $window = Gtk2::Window->new(); $window->signal_connect('delete_event' => sub { Gtk2->main_quit; }); $window->set_default_size(500, 500); $window->set_border_width(5); my $vBox = Gtk2::VBox->new(FALSE, 0); $window->add($vBox); # Draw a Gtk2::Frame containing a Gnome2::Canvas # The frame should be as long as possible, but only 50 pixels high my $frameHeight = 50; my $frame = Gtk2::Frame->new(undef); $frame->set_border_width(0); $frame->set_size_request(-1, $frameHeight); my $canvas = Gnome2::Canvas->new(); # (This line appears to move the canvas to the top-left corner of # the frame) $canvas->set_center_scroll_region(FALSE); $frame->add($canvas); $vBox->pack_start($frame, FALSE, FALSE, 0); # Draw a red bar, almost as long as the frame, but with a fixed height my ($width, $height) = $canvas->get_size(); my $rect = Gnome2::Canvas::Item->new( $canvas->root(), 'Gnome2::Canvas::Rect', x1 => 20, y1 => 20, x2 => ($width - 40), y2 => ($frameHeight - 20), fill_color => '#FF0000', outline_color => '#000000', ); $rect->raise_to_top(); $window->show_all(); Gtk2->main;

Replies are listed 'Best First'.
Re: Can't position Gnome2::Canvas within Gtk2::Frame
by syphilis (Archbishop) on Oct 06, 2017 at 21:43 UTC
    Hi,
    Just a couple of observations.

    You have:
    $canvas->set_center_scroll_region(FALSE);

    In order to centralise the red bar, I find that I need to specify that as TRUE.

    It seems to me that you haven't specified any size for the canvas, and that it would therefore be expected to be the default size of (100, 100).
    You have specified a window size of (500, 500) and $window->get_size() does, indeed, return (500, 500).

    You might also try the gtk-perl mailing list for some assistance, given that good help from this forum is a little slow in coming.

    Update: On re-reading your post, I see that I haven't really told you much that you hadn't already worked out for yourself. Sorry 'bout that.
    It does seem that the slight off-centredness that you see is because the red bar is specified to be between 20 and $width-40.
    Change that to x2 => ($width - 20) and it should be centred. Alternatively, specify x1 => 40 and you'll also achieve centring (though the red bar will then be shorter by 20).

    I don't know how to centre a non-default size canvas. I expected this to work:
    $canvas->set_size(400, 100); $canvas->set_center_scroll_region(TRUE); $frame->add($canvas);

    but the canvas size is still (100, 100).So I tried:
    $canvas->set_center_scroll_region(TRUE); $canvas->set_size(400, 100); $frame->add($canvas);

    and the canvas size is then the specified (400, 100) but "centred" for a canvas size of (100, 100) and therefore completely off centre.

    Cheers,
    Rob

      Thanks, Rob. One working solution is to use ->allocate(). Another is to use Gtk2::Gdk::Cairo::Context instead of Gnome2::Canvas.

      Both are posted below, in case anyone is interested.

      #!/usr/bin/perl use strict; use diagnostics; use warnings; use Gtk2 '-init'; use Glib qw(TRUE FALSE); use Gnome2::Canvas; # Draw a Gtk2 window my $window = Gtk2::Window->new(); $window->signal_connect('delete_event' => sub { Gtk2->main_quit; }); $window->set_default_size(500, 500); $window->set_border_width(5); my $vBox = Gtk2::VBox->new(FALSE, 0); $window->add($vBox); # Draw a Gtk2::Frame containing a Gnome2::Canvas # The frame should be as long as possible, but only 50 pixels high my $frame = Gtk2::Frame->new(undef); $frame->set_border_width(0); $frame->set_size_request(-1, 50); my $canvas = Gnome2::Canvas->new(); $frame->add($canvas); $vBox->pack_start($frame, FALSE, FALSE, 0); # The ->show_all() call here makes everything work (for some reason) $window->show_all(); my $rect = $canvas->allocation(); $canvas->set_scroll_region( 0, 0, $rect->width, $rect->height, ); # Draw a red bar, almost as long as the frame, but with a fixed # height, centred in the middle my ($width, $height) = $canvas->get_size(); # (The Gtk2::Frame is 490x50, so the Gnome2::Canvas should be 488x48) #print "canvas w $width h $height\n"; my $canvasItem = Gnome2::Canvas::Item->new( $canvas->root(), 'Gnome2::Canvas::Rect', x1 => 20, y1 => 20, x2 => ($width - 20), y2 => ($height - 20), fill_color => '#FF0000', outline_color => '#000000', ); $canvasItem->raise_to_top(); $window->show_all(); Gtk2->main;

      Second one...

      #!/usr/bin/perl use strict; use diagnostics; use warnings; use Gtk2 '-init'; use Glib qw(TRUE FALSE); # Draw a Gtk2 window my $window = Gtk2::Window->new(); $window->signal_connect('delete_event' => sub { Gtk2->main_quit; }); $window->set_default_size(500, 500); $window->set_border_width(5); my $eBox = Gtk2::EventBox->new(); $eBox->set_app_paintable(TRUE); $eBox->signal_connect('expose_event' => \&draw_event_box); my $Label1 = Gtk2::Label->new("Label1"); $Label1->set_markup("<span foreground='green' font='25'>Label1</span>" +); my $Label2 = Gtk2::Label->new("Label2"); $Label2->set_markup("<span foreground='red' font='25'>Label2</span>"); my $vBox = Gtk2::VBox->new(FALSE, 0); $vBox->pack_start_defaults($Label1); $vBox->pack_start_defaults($Label2); $eBox->add($vBox); $window->add($eBox); $window->show_all(); Gtk2->main; sub draw_event_box { my ($widget, $event, $user_data) = @_; my $cr = Gtk2::Gdk::Cairo::Context->create( $widget->window ); my $rectangle = $widget->allocation; #Paint background. $cr->set_source_rgb(0, 1, 1); $cr->paint; #Draw yellow line in middle. $cr->set_source_rgb(1, 1, 0); $cr->set_line_width(10); $cr->move_to(0, ($rectangle->height) / 2); $cr->line_to($rectangle->width, ($rectangle->height) / 2); $cr->stroke(); #Draw frame. $cr->set_source_rgb(0, 0, 1); $cr->set_line_width(15); $cr->rectangle(0, 0, $rectangle->width, $rectangle->height); $cr->stroke(); return FALSE; }
        Both are posted below, in case anyone is interested

        I'm (obviously) not very knowledgeable on Gtk, and it always seems to me that one has to pull things out of mid-air.
        Maybe things would appear a little less arcane if I actually read the documentation ;-)

        Thanks for taking the time to post those 2 approaches here. They both work fine for me on Windows.

        Cheers,
        Rob