What's cooking in grandma's kitchen ?

Its always something that smells good and makes me hungry. Why not share some of her tasty recipes for cooking with gtk2-perl ?

Most of the nifty concoctions that you see here come from contributions to our mailing list. One's too exotic to be left in the mailing list archive will be garnished and presented here for your enjoyment.

How is this different from the FAQ page ?

FAQ is for short snippets to answer frequently asked questions. That's like your daily staple diet. But for special occasions, like that special date, you may want to cook up something exotic. And that's when you read these recipes.

How can I contribute ?

Got your favourite recipe ? Just add it to list below. If you have a reference to the source of the code (like an email thread, for example) include that too.

Favourite recipes

In summertime a frozen TreeView just tastes good !


I'd like to freeze a tree view column (the first one) so that horizontal scrolling will always show this column. Like in a spreadsheet. Is this posible?


The Gtk2::TreeView is neither a sheet widget nor M$ Excel. But what you can do is use a paned widget, with a single-column view in the left pane and a multi-column view in the right pane. Both views can look at the same model, and you can make them both use the same scrollbar adjustments so they will scroll together.

use strict;
use Gtk2 -init;

my $model = Gtk2::ListStore->new (('Glib::Int')x16);
for (0..99) {
    $model->set ($model->append,
                 0, $_,
                 map { ($_, int (255 * rand())) } 1..$model->get_n_columns-1

my $window = Gtk2::Window->new;
my $paned = Gtk2::HPaned->new;
my $view1 = Gtk2::TreeView->new ($model);
my $view2 = Gtk2::TreeView->new ($model);

# left view, showing only the first column
my $col = Gtk2::TreeViewColumn->new_with_attributes
                        ('Col 0', Gtk2::CellRendererText->new, text => 0);
$view1->append_column ($col);

# right view, showing the remaining columns
for (1..$model->get_n_columns-1) {
        $col = Gtk2::TreeViewColumn->new_with_attributes
                        ("Col $_", Gtk2::CellRendererText->new, text => $_);
        $view2->append_column ($col);

# place the first view in the left pane by itself.
$paned->add1 ($view1);
# VERY IMPORTANT - tell the view not to try to display all of its rows.
# we set the vertical size request very small, and it will fill up the
# available space when we set the default size of the window.
$view1->set_size_request (-1, 10);

# the second view goes in the right, inside a scrolled window.
my $scroll2 = Gtk2::ScrolledWindow->new;
$scroll2->add ($view2);
$paned->add2 ($scroll2);

# linked scrolling
$view1->set (vadjustment => $scroll2->get_vadjustment);

# linked selection
$view1->get_selection->signal_connect (changed => \&sync_selection, $view2);
$view2->get_selection->signal_connect (changed => \&sync_selection, $view1);
sub sync_selection {
        my ($selection, $otherview) = @_;
                                (scalar $selection->get_selected);

$window->add ($paned);
$window->set_default_size (400, 400);
$window->signal_connect (destroy => sub {Gtk2->main_quit});

Why not cook up a TreeStore from scratch ? Like in olden times...


Is it worth implementing my own custom TreeStore ? If yes, then how do I do that ?


Gtk2::TreeView uses the MVC architecture. This means that while the Gtk2::TreeView functions as the view, the Gtk2::TreeModel functions as model for that view. In order to make life simpler for programmers who do not need to write their own specialized model, two generic models are provided - the Gtk2::TreeStore and the Gtk2::ListStore.

While the two pre-packaged generic models will suffice most of your needs, this does not prevent you from writing your own implementation of the Gtk2::TreeModel. But let me warn you, its not for the weak-at-heart.

If you still want to write your own Gtk2::TreeModel, here's the way to go !

(The actual implementation is left as an exercise to the reader ! ;) )

How do I create a image from a scalar ?


I have a library (GD::Graph, GD::Dashboard, etc) that can create an image and put it in scalar reference. It can also make a physical file on the file system which I can load in with Gtk2::Image->new_from_file("file.png"). Is there a way to take the scalar that the library produces and load that into the application without having to write the file to the file system and read it again.


If these libraries can create uncompressed image data, then you can create an image without going to disk through the Gtk2::Gdk::Pixbuf->new_from_data function

For example, here is a way to directly display piddles (Perl Data Language structures)

  my($w,$h) = ($rgb->dims)[1,2];
  my $img = Gtk2::Gdk::Pixbuf->new_from_data(${$rgb->get_dataref},
                                              0, 8,
                                              $w,$h, $w*3);

The $rgb->get_dataref call returns (a reference to) a scalar containing the RGB values. The pixbuf is then easily placed in an Gtk::Image .

If you want to load a png image, you have to use a Gtk2::Gdk::PixbufLoader and simulate an incremental read.

  my $loader = Gtk2::Gdk::PixbufLoader->new;
  $loader->write ($compressed_data);
  my $pixbuf = $loader->get_pixbuf;

I want to employ my own fancy sort algorithm on my treeview header. How do I do that ?


Say you have some sophisticated sort algorithm you need to apply to a column of data in a tree, and the sort algorithm takes parameters that you can tweak. You'd like to allow the user to select those parameters from a context menu that pops up from the header button, that same button you click to change sort column and sort order.


Define a treeview and then define a custom sort func that sorts on the virtual column.

sub foosort {
    my ($liststore, $itera, $iterb, $sortkey) = @_;

Use different sort column ids for the different sort options.

$model->set_sort_func (0, \&foosort, 0);
$model->set_sort_func (1, \&foosort, 1);
$model->set_sort_func (2, \&foosort, 2);

Now, here comes the heavy wizardry. We want to allow the user to right-click on the column heading to pop up a context menu. To do this, we need to get a hold of the button that's used as the column header. There is no sanctioned "clean" way to get this button, we can cheat by seeking up the widget hierarchy for it.

We must start off by setting a custom widget into the column. get_widget() will return undef unless we've previously called set_widget(), so let's create a label we can use as the heading label. We'll also use this label to show which virtual column is used for sorting.

my $label = Gtk2::Label->new ($col->get_title." (0)");
$col->set_widget ($label);
$label->show;  # very important, show_all doesn't get this widget!

And now, we need to find the button. To avoid problems in the future should the actual layout of widgets change, we'll seek instead of just assuming it's always three layers deep. If you're really paranoid, you can modify this to avoid the possibility of infinite looping, but in this case we know there's a button in the tree.

my $button = $col->get_widget; # not a button
do {
    $button = $button->get_parent;
} until ($button->isa ('Gtk2::Button'));

Rest of the code is pretty straight-forward. First we'll listen to the 'button-release-event'. We should return immediately if it is not a right-click because we want the regular tree-sort to go on.

$button->signal_connect (button_release_event => sub {
    my (undef, $event) = @_;
    # Do completely normal things unless this is a right-button click.
    return FALSE unless $event->button == 3;

If it indeed is a right-click, then pop up a context menu that lets the user select the virtual column on which to sort. Based on the user selection in the pop up menu, perform a sort on the $sortkey.

$col->set_sort_column_id ($sortkey);
$model->set_sort_column_id ($sortkey,
# update the column heading to show which virtual
# column is active.
$label->set_text ($col->get_title." ($sortkey)");

A complete working example can be found at

How do I trap a key-press and do something clever with it ?


I want to call a subroutine and do something clever when a certain key is pressed. I know I can do that with a menubar at the top but what if I don't want a menubar at the top ?


One approach is to connect a callback to either 'key-press-event' or 'key-release-event', then switch on the keyval in the event structure you get. return true if you handle it, otherwise false lets the rest of the processing happen.

One thing to remember is that you may have a really hard time catching key events for certain widgets, specifically if the widgets do a lot of drawing and charting and are usually plain DrawingAreas. Such widgets by default don't take key events.

Under these circumstances, best results may be achieved by hooking the 'key-press-event' on the toplevel window containing the widgets.

# Remember to load the module which contains all the keycodes!!!
use Gtk2::Gdk::Keysyms;

$toplevelwindow->signal_connect (key_press_event => sub {
    my ($widget, $event) = @_;
    return  unless $event->keyval == $Gtk2::Gdk::Keysyms{Escape};
    abort_some_long_running_process ();
    return 1;

How can I use different colored text in a Gtk2::TreeView ?


I want to have particular cells in a Gtk2::TreeView to be highlighted in different colours depending on the data.


If all of the cells in a column will be the same color, you can do

$renderer->set (foreground => 'red',   # there's also foreground-gdk
           foreground_set => TRUE);    # so it gets used

If different rows should have different colors, there are two approaches you can use.

  • Calculate the color to use and store it in a column in your Gtk2::TreeModel, and then set up a TreeViewColumn attribute to use that column to set the foreground color.

$renderer = Gtl2::CellRendererText->new;
$renderer->set (foreground_set => TRUE);
$column = Gtk2::TreeViewColumn->new_with_attributes
                         text => $text_column_index,
                         foreground => $color_column_index);
  • Or, you can calculate the color on the fly in a cell data function. this can get pretty processing-intensive, but is the only way to handle some extremely dynamic data. the cell data func gets called every time the column goes to draw a cell; its purpose is to set the properties of the cell renderer, so the renderer draws the right stuff.

$column = Gtk2::TreeViewColumn->new;
$renderer = Gtk2::CellRendererText->new;
$renderer->set (foreground_set => TRUE);
$column->pack_start ($renderer, TRUE);
$column->set_cell_data_func ($renderer, sub {
        my ($column, $cell, $model, $iter) = @_;
        # use an interesting and sophisticated algorithm to
        # determine what text to display and what color it
        # should be (a la spreadsheet cell functions, where
        # the contents of the cell are not what is displayed)
        my ($text, $color) = do_something_cool ($model, $iter);
        $cell->set (text => $text,
                    foreground => $color);

There is another example of using a cell data func in Gtk2/examples/ -- the custom cell data func formats data from a Gtk2::Scalar column in the model, where the scalars are array references; without the cell data func, the renderer shows "ARRAY(0xabcdef)" etc. The nice thing about the cell data func is that you can do anything you want. the drawback is that it is very easy to make your treeview render sluggishly, so you need to optimize your code there.

I wish I could change the color of a treeview cell by touching it !


I want to let the user highlight certain cells of the treeview by clicking on them. Like a magic marker.


While defining the treeview, ensure that you have a column reserved for the background color.

my $col = Gtk2::TreeViewColumn->new_with_attributes($column, $cell, text => $i, background => $i+1);

Then trap the 'button-release-event' on the treeview and identify the cell on which the event occurred using the {$tree_view->get_path_at_pos function.

$tree_view->signal_connect('button-release-event' =>
    sub {        
        my ($self, $event) = @_;
        my ($path, $column, $cell_x, $cell_y) = $tree_view->get_path_at_pos ($event->x, $event->y);


Now since you know exactly the cell that you have clicked, just change the color set in the model.

my $iter = $model->get_iter ($path);
# Change the background of the cell that was clicked
my $current_color = $model->get($iter, $i*2+1);
my $new_color = defined $current_color ? undef : 'green';
$model->set($iter, $i*2+1, $new_color);

For a full working example, follow the thread

Can I programmatically edit a cell in the Gtk2 TreeView ?


If I put an editable CellRendererText in a TreeView, I get the funcionality of editing the text when double-clicking a node. Now, how can I start the edit without double-clicking a node? For instance, if I want to start editing after I click on a Button, how do I do that?


First set the cursor on the cell that you want to edit

$treeview->set_cursor (Gtk2::TreePath->new_from_string("0:1:0"), $treeview_columns->[3], TRUE);

Now activate the root window that the treeview is in


How can I programmatically popup a tooltip ?


Is there a way to programmatically popup a tooltip using Gtk2::Tooltip ?


Gtk2::Tooltip does not provide the functionality to programmatically invoke it. If you want to desperately know why, try

However, if you are desperate to get the tooltip effect, you can achieve the same using a popupwindow and some duct-tape.

Here is a recipe. First prepare our little popup tooltip window.

# This is our little tooltip window.
my $tooltip_label = Gtk2::Label->new;
my $tooltip = Gtk2::Window->new('popup');
$tooltip->set_position('mouse'); # We'll choose this to start with.
$tooltip->modify_bg ('normal', Gtk2::Gdk::Color->parse('yellow')); # The obligatory yellow
my $tooltip_displayed = FALSE;

I assume you want to popup the tooltip based on your mouse position. i.e., you want to popup when the (x,y) coordinates of the mouse lie in a certain range. For example, let us say that you want to popup a tooltip when the mouse is on certain areas of a large Gtk2::Image.

First we need to trap the mouse position. Now, the Gtk2::Image itself does not respond to mouse movements. Therefore, you need to first wrap it into a Gtk2::EventBox

my $image = Gtk2::Image->new_from_file('myimage.png');

# Image can't detect events. So load it into an eventbox explicitly.
my $eventbox = Gtk2::EventBox->new;
$eventbox->add ($image);
$eventbox->add_events (['pointer-motion-mask', 'pointer-motion-hint-mask']);

Then you need to listen to the mouse movements. And on 'motion-notify-event', you extract the (x,y) coordinates of the event.

$eventbox->signal_connect ('motion-notify-event' => 
    sub {
        my ($widget, $event) = @_;
        my ($x, $y) = ($event->x, $event->y);
        # If the image is smaller than the window, we need to 
        # translate these window coords into the image coords.
        # Get the allocated size of the image first.
        # I assume that the image is always centered within the allocation.
        # Then the coords are transformed.
        # $imagesize is the actual size of the image (in this case the png image)
        my @imageallocatedsize = $image->allocation->values;
        $x -= ($imageallocatedsize[2] - $imagesize[0])/2;
        $y -= ($imageallocatedsize[3] - $imagesize[1])/2;

Now since you have the relative (x,y) coordinates, we will check to see whether this (x,y) falls within the range (hotspot) that we are interested in.

if (on_hotspot($x,$y)) {
    if (!$tooltip_displayed) {
        my ($thisx, $thisy) = $tooltip->window->get_origin;
        # I want the window to be a bit away from the mouse pointer.
        # Just a personal choice :)
        $tooltip->move($thisx, $thisy-20);
        $tooltip_displayed = TRUE;
else {
    $tooltip_displayed = FALSE;

A complete working example is available in

Show me a recipe to create a context-sensitive menu


When the user right-clicks on my widget, I want a menu to popup. The user should be able to select an item from the menu and I want a correspoding action to take place.


What you are looking for is a context-sensitive menu. A common feature in UI applications. Well, here is the recipe.

First task is to ensure that your widget indeed is sensitive to the mouse click. Most likely, you want to click on a Gtk2::Image or a Gtk2::Label. These widgets are insensitive to events. So you need to wrap them in a Gtk2::EventBox

my $label = Gtk2::Label->new('Right Click here');
my $eventbox = Gtk2::EventBox->new;
$eventbox->add ($label);

Now add the 'button-press-mask' to the eventbox. Then listen to the 'right-click' and popup a menu.

$eventbox->signal_connect ('button-press-event' => 
        sub {
                my ($widget, $event) = @_;
                return FALSE unless $event->button == 3;
                        undef, # parent menu shell
                        undef, # parent menu item
                        undef, # menu pos func
                        undef, # data

But we should've defined the $menu beforehand. Here is a definition.

my $menu = Gtk2::Menu->new();

my $menuitem1 = Gtk2::MenuItem->new("Coke");
my $menuitem2 = Gtk2::MenuItem->new("Pepsi");
my $menuitem3 = Gtk2::MenuItem->new("Fanta");

$menuitem1->signal_connect(activate => sub { print "You like coke ?\n" });
$menuitem2->signal_connect(activate => sub { print "Is pepsi any different ?\n" });
$menuitem3->signal_connect(activate => sub { print "Fanta is orangey ?\n" });



That's it. Enjoy

Making a screen shot from inside a Gtk2 application


How do I make a screen shot from within a Gtk2 application ? I want to do it without any external tools.


my ($width, $height) = $mywidget->window->get_size;

# create blank pixbuf to hold the image
my $gdkpixbuf = Gtk2::Gdk::Pixbuf->new ('rgb',

    ($mywidget->window, undef, 0, 0, 0, 0, $width, $height);

$gdkpixbuf->save ($file, "jpeg");

CellRendererCombo in a TreeView


How do I use a Gtk2::CellRendererCombo in a Gtk2::TreeView ?


use strict;
use Gtk2 -init;
use Glib ':constants';

# create a bunch of models to hold the appropriate choices for the various rows
my @combo_models;
foreach my $data 
                [qw(one two three four five)],
                [qw(red orange yellow green blue indigo violet)],
                [qw(george john paul ringo)],
                [qw(north south east west)]
        my $model = Gtk2::ListStore->new (qw(Glib::String));
        foreach my $string (@$data) {
                $model->set ($model->append, 0, $string);
        push @combo_models, $model;

# create and populate the main list
use constant NAME_COLUMN => 0;
use constant CURRENT_COLUMN => 1;
use constant MODEL_COLUMN => 2;
my @column_types;
$column_types[NAME_COLUMN] = 'Glib::String';
$column_types[CURRENT_COLUMN] = 'Glib::String';
$column_types[MODEL_COLUMN] = 'Gtk2::ListStore';
my $model = Gtk2::ListStore->new (@column_types);
foreach my $data 
                { name => 'Fred', current => 1, model => $combo_models[0] },
                { name => 'Barney', current => 2, model => $combo_models[1] },
                { name => 'Wilma', current => 3, model => $combo_models[2] },
                { name => 'Betty', current => 0, model => $combo_models[3] },
                { name => 'Pebbles', current => 2, model => $combo_models[0] },
                { name => 'Bam-Bam', current => 3, model => $combo_models[1] },
        $data->{current} = $data->{model}->get(
                $data->{model}->iter_nth_child (undef, $data-> {current}), 0
        $model->set (
                NAME_COLUMN, $data->{name},
                CURRENT_COLUMN, $data->{current},
                MODEL_COLUMN, $data->{model}

# create a view for that model.
my $treeview = Gtk2::TreeView->new ($model);

        (-1, 'Name', Gtk2::CellRendererText->new, text => NAME_COLUMN);

my $combo_renderer = Gtk2::CellRendererCombo->new;
$combo_renderer->set (
        text_column => 0, # col in combo model with text to display
        editable => TRUE
); # without this, it's just a text renderer
$combo_renderer->signal_connect (edited => 
        sub {
                my ($cell, $text_path, $new_text) = @_;
                $model->set (
                        $model->get_iter_from_string ($text_path),
                        CURRENT_COLUMN, $new_text
        -1, 'Selection', 
        text => CURRENT_COLUMN, 
        model => MODEL_COLUMN

# put all that on the screen
my $window = Gtk2::Window->new;
$window->signal_connect (destroy => sub { Gtk2->main_quit });
$window->add ($treeview);

Display a tooltip if the mouse hovers over a treeview cell


I want to display a tooltip if the mouse hovers over a treeview cell? Any ideas? There is no treecolumn attribute to get a tooltip string from a column.


This functionality will probably will available by default with Gtk2::TreeView some time in the near future.

But till then, you can fake this functionality by listening to the motion-notify-event of the Gtk2::TreeView.

Define a $popuphash->{$row}->{$column} to contain the tooltip text by row and column.

$tree_view->signal_connect('motion-notify-event' =>
        sub {        
                my ($self, $event) = @_;
                my ($path, $column, $cell_x, $cell_y) = $tree_view->get_path_at_pos ($event->x, $event->y);
                if ($path) {
                        my $model = $tree_view->get_model;
                        my $i = $column->{column_number};
                        my $row = $path->to_string();
                        # If a new cell is selected, then hide the tooltip
                        # It'll be re-shown as required by the code down under
                        if ($selected_row ne $row or $selected_col != $i) {
                                $tooltip_displayed = FALSE;
                                $selected_row = $row;
                                $selected_col = $i;
                        if ($row) {
                                # Pick that popup string from our hash
                                my $str = $popup_hash->{$row}->{$i};
                                if ($str) {
                                        if (!$tooltip_displayed) {
                                                my ($thisx, $thisy) = $tooltip->window->get_origin;
                                                # I want the window to be a bit away from the mouse pointer.
                                                # Just a personal choice :)
                                                $tooltip->move($thisx, $thisy-20);
                                                $tooltip_displayed = TRUE;
                        return 0;

A working example can be found here

Running a custom sub when the user closes the window


If someone clicks the window's close button, how do I prevent the window from closing immediately ? I can run code when this happens ( by connecting to the window's destroy signal ), but by the time my code runs, it's too late - the window is already gone.


Connect to the delete-event signal of the toplevel window. The default handler for the signal destroys the window; if you return true from your handler, the default handler will not run.

For example:

use strict;
use Gtk2 -init;

my $window = Gtk2::Window->new;
$window->add (Gtk2::Label->new ("I'm a banana!"));

$window->signal_connect (delete_event => 
    sub {
        return ! ask ($_[0], "Really quit?");

$window->signal_connect (destroy => sub { Gtk2->main_quit });

sub ask {
    my ($parent, $question) = @_;
    my $msgbox = Gtk2::MessageDialog->new ($parent, [], 
        'yes-no', $question
    my $response = $msgbox->run();
    return $response eq 'yes';

Using pixbufs in a column in Gtk2::Ex::Simple::List


I wish I could use little images in a column in my Gtk2::Ex::Simple::List. Is it even possible ?


Of course it is possible.

use strict;
use Gtk2 -init;
use Gtk2::Ex::Simple::List;

my $window = Gtk2::Window->new;
$window->signal_connect (destroy => sub { Gtk2->main_quit });

my $slist = Gtk2::Ex::Simple::List->new (
        'Icon' => 'pixbuf',
        'Stock-Id' => 'text'

# I'm too lazy to create a bunch of pixbufs here, so i want to use
# stock items. Gtk2::CellRendererPixbuf can, indeed, use a stock id,
# but the 'pixbuf' column type for SimpleList wants an actual pixbuf
# object. So, here's a little perl magic to render these stock icons
# as we will the store. Remember, the SimpleList represents the
# TreeStore as a list of lists, so the map block must return a
# reference an array of column values...

@{ $slist->{data} } = 
    map {
                # column 0, the pixbuf column 1, the text
                [ $window->render_icon ($_, 'menu'), $_ ]
        } qw(gtk-ok gtk-cancel gtk-yes gtk-no gtk-save gtk-open gtk-quit gtk-close);

$window->add ($slist);

Blending gtk2-perl code with C


Perl (and gtk2-perl) provides ease of application development and C provides raw performance gains. Sometimes you just want the best of both worlds and feel like writing your application as a blend of the two. What is a good strategy to go about this ?


Take a look at this email thread.

Projects/GTK-Perl/Recipes (last edited 2015-01-16 10:34:54 by EmmanueleBassi)