Gtk2::TreeView
A Gtk2::TreeView
offers you the opportunity to manually change displayed text.
This lesson will discuss how to go about editing text displayed by Gtk2::CellRendererText
.
You have to set the "editable" property of the Gtk2::CellRendererText
to "TRUE". This will ONLY allow you to change the text displayed by the cell renderer, but as soon as you change focus to somewhere outside the cell, the cell's value will revert to its original value.
You can set the "editable" property of the Gtk2::CellRendererText
on two ways
The properties can be set for all rows by using Glib::Object
's set_property()
method.
$renderer_txt->set_property('editable', TRUE);
You can set it row by row, when using the Gtk2::TreeViewColumn
's add_attribute
and set_attributes
methods.
$tree_column->add_attribute($cell_renderer,'editable'=> COLUMN_EDITABLE);
When you have a few cell renderers next to each other (a few Gtk2::TreeViewColumn
s, each containing one or more Gtk2::CellRenderer
), you can use the same callback, BUT need to differentiate inside the callback which cell renderer was edited.
We do this by attaching a "data-rider" to the cell renderer.
#Attach a 'renderer_number' value to the renderer. #This can be used to differentiate between renderers #when we have a few renderers which can be edited $renderer->{'renderer_number'} = RENDERER_FIRST_TEXT;During the callback we can then discover which renderer was edited.
In order to set the cell's value to the new value, you have to connect the "edited"
signal to a callback that will set the cell's previous value to the new value. This is the same callback mentioned in the above point.
It is good practice to declare constants for each column in the use constant COLUMN_EDITABLE => 2;assigns a constant of "COLUMN_EDITABLE" to the int value "2". When using this constant, you know what it is suppose to represent. The same can be done with the cell renderer "data-rider" values. #Create a constant to differentiate different renderers; #This makes things easy to discover which renderer in the view #was changed use constant RENDERER_FIRST_TEXT => 0;Remember that Gtk2::TreeViewColumn s are unrelated to Gtk2::TreeModel columns. During the callback routine we need to link them up in code.
|
To see which properties are available to set for each cell renderer, look at |
A working example can be found here: 'Editing text in a Gtk2::TreeView
'
This program is not much different from the previous demo, so it would waste space showing the whole program again. We will only discuss the parts of interest here.
To make the Gtk2::CellRendererText
ediable:
$renderer->set_property('editable' => TRUE);
To connect a 'data-rider' to the Gtk2::CellRenderer
:
#Attach a 'renderer_number' value to the renderer. #This can be used to differentiate between renderers #when we have a few renderers which can be edited $renderer->{'renderer_number'} = RENDERER_FIRST_TEXT;This is done before we connect the
"edited"
signal to the callback.
To connect a callback to the "edited"
signal:
$renderer->signal_connect (edited => \&cell_edited, $tree_store);We pass it the
Gtk2::TreeModel
implementation in the form of $tree_store. This will allow us to modify the value of the cell in the "cell_edited"
sub.
The "cell_edited"
sub is handed the following:
my ($cell, $path_string, $new_text, $model) = @_;We will then use the variables handed to the sub, to update the model.
To discover which Gtk2::CellRenderer
inside the Gtk2::TreeView
was edited, we extract the value of 'render_number' from the cell renderer. We then decide in code which column of the Gtk2::TreeModel
needs to be updated.
#Get the renderer number; my $column_of_model; if ($cell->{'renderer_number'} == RENDERER_FIRST_TEXT) { $column_of_model = MODEL_FIRST_COLUMN; }The way you associate the 'renderer_number' value to a
Gtk2::TreeModel
column does not need to be a simple "if" statement. You can use a more slick lookup hash.
The above may seem like an overkill, because we only have one |
We generate a Gtk2::TreePath
, by using $path_string as a argument to the new_from_string
method of Gtk2::TreePath
.
my $path = Gtk2::TreePath->new_from_string ($path_string);This will give us a "geographical" indication which row was edited.
We then get the Gtk2::TreeIter
of the Gtk2::TreePath
, $path.
my $iter = $model->get_iter ($path);$iter is now referring to a row in model-speak.
Remember the actual goal of changing a value in the model? We accomplish our goal with the following:
$model->set_value ($iter, $column_of_model, $new_text);
Looking at it as a unit:
sub cell_edited { my ($cell, $path_string, $new_text, $model) = @_; #Get the renderer number; my $column_of_model; if ($cell->{'renderer_number'} == RENDERER_FIRST_TEXT) { $column_of_model = MODEL_FIRST_COLUMN; } my $path = Gtk2::TreePath->new_from_string ($path_string); my $iter = $model->get_iter ($path); $model->set_value ($iter, $column_of_model, $new_text); }
The above principle is also used on the Gtk2::CellRendererToggle
. In order to make changes apply to the underlying model, you have to connect a signal callback to its "toggled"
signal.
The callback will receive the following:
my ($cell, $path_str, $model) = @_;You then need to read the current state of the
Gtk2::CellRendererToggle
from the model, invert it and write it back to the model so it can again be reflected by the Gtk2::CellRendererToggle
that was "toggled"
. The rest can be done in much the same way Gtk2::CellRendererText
did it.