Gtk2::CellRenderer
s Gtk2::TreeViewColumn
s and Gtk2::CellRenderer
s work together to display a column of data in a Gtk2::TreeView
. The Gtk2::TreeViewColumn
provides the column title and a vertical space for the Gtk2::CellRenderer
s to render a portion of the data from the Gtk2::TreeView
data store. A Gtk2::CellRenderer
handles the rendering of each row and column data within the confines of the Gtk2::TreeViewColumn
. A Gtk2::TreeViewColumn
can contain more than one Gtk2::CellRenderer
to provide a row display similar to an Gtk2::HBox
. A common use of multiple Gtk2::CellRenderer
s is to combine a Gtk2::CellRendererPixbuf
and a Gtk2::CellRendererText
in one column.
This lesson will look at various ways to present the data of the Gtk2::TreeView
data store in Gtk2::CellRenderer
s.
Gtk2-Perl
provides five pre-defined cell renderers. We will only look at three of them in this lesson. They are subclasses of Gtk2::CellRenderer
. If they do not supply a means to display your data, it is always possible to create your own subclass.
Table 14-2. Pre-defined Gtk2::CellRenderer
Types
Gtk2 Class Name | Rendering Type |
---|---|
Gtk2::CellRendererPixbuf | Renders pixbuf images, either created by the program or one of the stock items. |
Gtk2::CellRendererText | Renders text strings, and numbers that can be converted to a string. |
Gtk2::CellRendererToggle | Renders a boolean value as a toggle button or a radio button. |
Gtk2::CellRendererCombo | A subclass of Gtk2::CellRendererText , renders a Gtk2::ComboBox into the cells of a Gtk2::TreeViewColumn |
Gtk2::CellRendererProgress | renders a progressbar into the cells of a Gtk2::TreeViewColumn .; |
Each of the pre-defined cell renderers has various properties that determine how the data will be rendered. Some of the properties is part of Gtk2::CellRenderer
, and gets inherited by all the subclasses. Each subclass also feature its own set of properties. To find available properties, consult the man pages.
To associate a tree model column with a Gtk2::CellRenderer
property, you define an attribute to the Gtk2::TreeViewColumn
. The Gtk2::CellRenderer
sets the property from the row's column value before rendering the cell. This allows you to customize the cell display by using tree model data. Consult the man page of Gtk2::TreeViewColumn
for the various methods available to add attributes to the Gtk2::TreeViewColumn
.
You will typically associate a column of type "Glib::String" in the tree model with the "text" or "markup" property of a Gtk2::CellRendererText
, and you are most likely to associate a column of type "Glib::Boolean" in the tree model with the "active" property of Gtk2::CellRendererToggle
.
The properties can be set for all rows by using $renderer_txt->set_property('cell-background', 'yellow'); |
Table 14-3. Gtk2
object classes used
Gtk2 Class Name |
---|
Gtk2::Window |
Gtk2::VBox |
Gtk2::ListStore |
Gtk2::TreeView |
Gtk2::TreeViewColumn |
Gtk2::CellRendererPixbuf |
Gtk2::CellRendererText |
Gtk2::CellRendererToggle |
Gtk2::TreePath |
The program can be found here: 'Rendering data'
1 #! /usr/bin/perl -w 2 3 use strict; 4 use Gtk2 '-init'; 5 use Glib qw/TRUE FALSE/; 6 7 #Declare our columns 8 use constant C_MARKUP => 0; 9 use constant C_BACKGROUND => 1; 10 use constant C_STOCK => 2; 11 use constant C_TOGGLE => 3; 12 13 #the data for the model 14 my @data = ( 15 16 {markup => '<b>This is Bold</b>', 17 background => 'red', 18 stock => 'gtk-open', 19 toggle => TRUE}, 20 21 {markup => '<span foreground="orange" size="15000"><i>Some Value</i></span>', 22 background => undef, 23 stock => 'gtk-close', 24 toggle => FALSE }, 25 26 { markup => '<span foreground="blue" size="30000"><u>Blue text</u></span>', 27 background => 'green', 28 stock => 'gtk-cdrom', 29 toggle => TRUE}, 30 31 ); 32 33 #standard window creation, placement, and signal connecting 34 my $window = Gtk2::Window->new('toplevel'); 35 $window->signal_connect('delete_event' => sub { Gtk2->main_quit; }); 36 $window->set_border_width(5); 37 $window->set_position('center_always'); 38 39 #this vbox will geturn the bulk of the gui 40 my $vbox = &ret_vbox(); 41 42 #add and show the vbox 43 $window->add($vbox); 44 $window->show(); 45 46 #our main event-loop 47 Gtk2->main(); 48 49 50 51 52 sub ret_vbox { 53 54 my $vbox = Gtk2::VBox->new(FALSE,5); 55 $vbox->set_size_request (500, 150); 56 57 #get the model 58 my $store = &create_model; 59 60 #create a treeview with the model. 61 my $treeview = Gtk2::TreeView->new_with_model($store); 62 63 #------------------------------------------------------------------ 64 #create a treeview column and set its title 65 my $tv_clmn_pix_text = Gtk2::TreeViewColumn->new; 66 $tv_clmn_pix_text->set_title("Pix and Markup"); 67 #pixbuf renderer 68 my $ren_stock = Gtk2::CellRendererPixbuf->new(); 69 #pack it into the column 70 $tv_clmn_pix_text->pack_start ($ren_stock, FALSE); 71 #set its atributes 72 $tv_clmn_pix_text->set_attributes($ren_stock, 73 'stock-id' => C_STOCK, 74 'cell-background'=> C_BACKGROUND, 75 ); 76 #text renderer 77 my $ren_text = Gtk2::CellRendererText->new(); 78 #pack it into the column 79 $tv_clmn_pix_text->pack_start ($ren_text, FALSE); 80 #set its atributes 81 $tv_clmn_pix_text->set_attributes($ren_text, 82 'markup' => C_MARKUP, 83 'cell-background' => C_BACKGROUND, 84 ); 85 #append this column to the treeview 86 $treeview->append_column($tv_clmn_pix_text); 87 88 #------------------------------------------------------------------ 89 #create a treeview column and set its title 90 my $tv_clmn_toggle_text = Gtk2::TreeViewColumn->new; 91 $tv_clmn_toggle_text->set_title("Toggle and Markup"); 92 #toggle renderer 93 my $ren_toggle = Gtk2::CellRendererToggle->new(); 94 $ren_toggle->signal_connect('toggled' => \&toggled,$store); 95 #pack it into the column 96 $tv_clmn_toggle_text->pack_start ($ren_toggle, FALSE); 97 #set its atributes 98 $tv_clmn_toggle_text->set_attributes($ren_toggle, 99 'active' => C_TOGGLE, 100 ); 101 #text renderer 102 my $ren_tgl_text = Gtk2::CellRendererText->new(); 103 #pack it into the column 104 $tv_clmn_toggle_text->pack_start ($ren_tgl_text, FALSE); 105 #set its atributes 106 $tv_clmn_toggle_text->set_attributes($ren_tgl_text, 107 'markup' => C_MARKUP, 108 ); 109 #append this column to the treeview 110 $treeview->append_column($tv_clmn_toggle_text); 111 112 #------------------------------------------------------------------ 113 $vbox->pack_start($treeview,TRUE,TRUE,0); 114 $vbox->show_all(); 115 return $vbox; 116 } 117 118 119 sub create_model { 120 # create list store 121 my $list_store = Gtk2::ListStore->new(qw/Glib::String Glib::String Glib::String Glib::Boolean/); 122 123 # add data to the list store 124 foreach my $d (@data) { 125 my $iter = $list_store->append; 126 $list_store->set ($iter, 127 C_MARKUP, $d->{markup}, 128 C_BACKGROUND, $d->{background}, 129 C_STOCK, $d->{stock}, 130 C_TOGGLE, $d->{toggle}, 131 ); 132 } 133 134 return $list_store; 135 } 136 137 sub toggled { 138 my ($cell, $path_str, $model) = @_; 139 140 my $path = Gtk2::TreePath->new_from_string ($path_str); 141 142 # get toggled iter 143 my $iter = $model->get_iter ($path); 144 my ($fixed) = $model->get ($iter, C_TOGGLE); 145 146 # do something with the value 147 $fixed =!$fixed; 148 149 # set new value 150 $model->set ($iter, C_TOGGLE, $fixed); 151 }
We start off practicing good programming practice by declaring the constants representing each of the columns in the model
#Declare our columns use constant C_MARKUP => 0; use constant C_BACKGROUND => 1; use constant C_STOCK => 2; use constant C_TOGGLE => 3;This makes things easier when you read the code, and in future when maintaining code, it will lighten your burden.
Next, the contents of the model is created. In your program you can use various sources to create contents. You may get it from an XML file or from the return of a SQL select statement. In this sample we hard coded it in the form of an array of hashes.
At this stage, it is not yet inserted into the Gtk2::ListStore
.
We call the create_model
sub to create and populate a Gtk2::ListStore
. We then return a reference to this Gtk2::ListStore
, and use it as the model for the newly created Gtk2::TreeView
.
#get the model my $store = &create_model; #create a treeview with the model. my $treeview = Gtk2::TreeView->new_with_model($store);
Adding the columns to the Gtk2::TreeView
follows a basic pattern of:
Create a Gtk2::TreeViewColumn
, set its title. This will be the container of the cell renderers.
Create a cell renderer. You can choose from predefined ones, or create your own.
Pack it into the Gtk2::TreeViewColumn
.
Add the attributes to the Gtk2::TreeViewColumn
. This will set the defined property of the cell renderer to the value of the specified column number in the model.
When we want a value to be the default, we can leave it undef
. This we did for the values of the "background" property.
After you packed all the required cell rederers into the Gtk2::TreeViewColumn
, add the Gtk2::TreeViewColumn
to the Gtk2::TreeView
using the append_column
method of the Gtk2::TreeView
.
We connect the "toggled" signal of the Gtk2::CellRendererToggle
to a sub that will change the underlying model of the Gtk2::TreeView
. It follows the simple procedure of getting the current value from the model, inverting it, and writing it back to the model.
This will then reflect on the Gtk2::CellRendererToggle
displaying that cell. If we neglect to do this, clicking on the renderer's check box will not cause a change of its state.
sub toggled { my ($cell, $path_str, $model) = @_; my $path = Gtk2::TreePath->new_from_string ($path_str); # get toggled iter my $iter = $model->get_iter ($path); my ($fixed) = $model->get ($iter, C_TOGGLE); # do something with the value $fixed =!$fixed; # set new value $model->set ($iter, C_TOGGLE, $fixed); }