Gtk2::Button
This lesson will look at the Gtk2::Button
class. We will also use one of Gtk2::Button
's subclasses called Gtk2::CheckButton
. This in itself is a subclass of Gtk2::ToggleButton
. So we have Gtk2::Button
->Gtk2::ToggleButton
->Gtk2::CheckButton
in the class hierarchy.
This lesson will also introduce three new widget classes. They are Gtk2::Frame
, Gtk2::ScrolledWindow
and Gtk2::Image
.
Last but not least, we will introduce the reader to the Gtk2::Stock
items and the cursor (Gtk2::Gdk::Cursor
).
Table 7-1. Gtk2 object classes used
Gtk2 Class Name |
---|
Gtk2::Window |
Gtk2::VBox |
Gtk2::Button |
Gtk2::CheckButton |
Gtk2::Frame |
Gtk2::Image |
Gtk2::ScrolledWindow |
Gtk2::Gdk::Cursor |
Gtk2::Stock |
Gtk2::Button
The Gtk2::Button
is a subclass of Gtk2::Bin
, so we can add only one child widget to it. By default, the text specified with the Gtk2::Button
->new()
method, will be added as a Gtk2::Label
class object. The newer versions of Gtk2-Perl
allows you to add a Gtk2::Image
class object with the Gtk2::Button
->set_image
method.
This is a nice feature to quickly create a picture button, or a button with a picture and a label. This saves time, as previously you first had to create a Gtk2::HBox
class object, then add a Gtk2::Image
and Gtk2::Label
instance, after that, add the Gtk2::HBox
to the Gtk2::Button
class object to create a picture button with a label next to it.
We can set the cursor with the set_cursor
method when it enter
and leave
the button. This simulates the effect of a hyper link, as we will see in the sample program.
The button also feature the mnemonic
functionality that was discussed as part of Chapter 6.
Gtk2::Frame
This class is one of those cosmetic classes, it is a Gtk2::Bin
subclass, so you can (just like Gtk2::Window
) add only one child widget to it.
Other cosmetic classes include Gtk2::HSeparator
and Gtk2::VSeparator
.
The Gtk2::Frame
does not have much features.
You can set its outline with the $frame->set_shadow_type ($type)
.
Another point worth mentioning is the label that traditionally accompany the Gtk2::Frame
.( widget = Gtk2::Frame->new ($label=undef)
or $frame->set_label ($label=undef)
) This is actually only a default. You can add any widget to the frame where the label usually resides. This is done by the $frame->set_label_widget ($label_widget)
method.
This feature is also available on the tabs of Gtk2::NoteBook
. This allows you to add a Gtk2::HBox
containing a label and a close button for instance to each tab.
In our sample program we add a Gtk2::CheckButton
to it. We will manipulate the appearance of the checkbutton as it gets clicked.
This class will be looked at in depth later on. In our sample program, we will create an instance of it by getting its data from a file.
Gtk2::ScrolledWindow
When one of your widget's length may change or you don't know what its initial size may be, or it is simply to long to fit onto your screen, you can put this long or wide widget into a Gtk2::ScrolledWindow
.
As you might have guessed, this is also a Gtk2::Container
subclass. There are basically three methods of importance.
$scrolled_window->set_policy ($hscrollbar_policy, $vscrollbar_policy)
This can take the option of always
, automatic
or never
. The rule of thumb is to set the side you want to scroll to automatic
and the one you don't want to scroll to never
.
$scrolled_window->set_shadow_type ($type)
This is used to make the scrolled window stand more out using a choice between none
, in
, etched-in
and etched-out
.
$scrolled_window->add_with_viewport ($child)
When you want to add a NON-SCROLLING widget, you do not use the Gtk2::Container
's add
method. This is the method you should use to add the NON-SCROLLING child widget.
[1]
Gtk2::Gdk::Cursor
The cursor may change depending over which widget it is hovering. The Gtk2::Entry
widget is an example where it will change. You can also specify what it should be.
In our sample program, we simulate the feel of a web browser by changing the cursor to a hand as soon as we enter
the checkbutton's area, and change it back again as when we leave
the checkbutton's area with the mouse.
$check_button->signal_connect('enter' => sub {$check_button->window->set_cursor($hand_cursor);});You will notice that we call the
window
property of $check_button. This is Gtk2::Gdk::Window
that we reference. We then use the set_cursor
method to set the cursor. To get the cursor back to normal, you do not have to remember what it was previously, just set it to undef
.
Thus, to set a cursor of a widget, we have to call its window
property.
$check_button->signal_connect('leave' => sub {$check_button->window->set_cursor(undef);});
Please node that |
Gtk2::Stock
Stock items are standard icons with labels that comes with Gtk+. A typical example is the "Ok" and "Cancel" buttons. This is powerful because the label change according to you language settings, making internationalization easier.
Stock items are special in the sense that, depending where it gets called, it may include a icon and a label, or just an icon. In our sample program, we call it to create a stock button. This includes the label to. If we create a Gtk2::Image
from stock, we will not get the label with it.
They are them dudes from the movie "Dude, where's my car?", dude!
The program can be found here: 'Button Demo'
1 #! /usr/bin/perl -w 2 use strict; 3 4 use Glib qw/TRUE FALSE/; 5 use Gtk2 '-init'; 6 7 #standard window creation, placement, and signal connecting 8 my $window = Gtk2::Window->new('toplevel'); 9 $window->signal_connect('delete_event' => sub { Gtk2->main_quit; }); 10 $window->set_border_width(5); 11 $window->set_position('center_always'); 12 13 #this vbox will geturn the bulk of the gui 14 my $vbox = &ret_vbox(); 15 16 #add and show the vbox 17 $window->add($vbox); 18 $window->show(); 19 20 #our main event-loop 21 Gtk2->main(); 22 23 24 sub ret_vbox { 25 26 my $hand_cursor = Gtk2::Gdk::Cursor->new ('hand2'); 27 #create a Gtk2::VBox to pack a Gtk2::Frame in. The frame will contain 28 #a Gtk2::ScrolledWindow, which in turn will contain a Gtk2::VBox full 29 #of Gtk2::Buttons 30 my $sw; 31 my $vbox = Gtk2::VBox->new(FALSE,5); 32 33 my $frame = Gtk2::Frame->new(); 34 #to prove that a Gtk2::Frame can contain somethethig else 35 # than a label 36 my $check_button = Gtk2::CheckButton->new ("Click Here!"); 37 38 $check_button->set_active (TRUE); 39 $check_button->signal_connect (toggled => sub { 40 my $self = shift; 41 if ($self->get_active){ 42 # 'activate' the scrolled window and chance the checkbutton's 43 # appearance if the user checks the check button. 44 my $img_dude = Gtk2::Image->new_from_file("./pix/sweet.jpg"); 45 #add a touch of detail 46 $window->set_icon_from_file ("./pix/dude.jpg"); 47 $sw->set_sensitive (TRUE); 48 $check_button->set_label("Sweet, and what about mine?"); 49 $check_button->set_property('image'=>$img_dude); 50 51 }else{ 52 # 'gray out' the scrolled window and chance the checkbutton's 53 # appearance if the user un-checks the check button. 54 my $img_sweet = Gtk2::Image->new_from_file("./pix/dude.jpg"); 55 #add a touch of detail 56 $window->set_icon_from_file ("./pix/sweet.jpg"); 57 $sw->set_sensitive (FALSE); 58 $check_button->set_label("Dude, what does mine say?"); 59 $check_button->set_property('image'=>$img_sweet); 60 } 61 }); 62 $check_button->show; 63 $check_button->signal_connect('enter' => sub {$check_button->window->set_cursor($hand_cursor);}); 64 $check_button->signal_connect('leave' => sub {$check_button->window->set_cursor(undef);}); 65 66 $frame->set_label_widget ($check_button); 67 $frame->set_shadow_type ('out'); 68 #method of Gtk2::Container 69 $frame->set_border_width(10); 70 71 $sw = Gtk2::ScrolledWindow->new (undef, undef); 72 $sw->set_shadow_type ('etched-out'); 73 $sw->set_policy ('never', 'automatic'); 74 #This is a method of the Gtk2::Widget class,it will force a minimum 75 #size on the widget. Handy to give intitial size to a 76 #Gtk2::ScrolledWindow class object 77 $sw->set_size_request (300, 300); 78 #method of Gtk2::Container 79 $sw->set_border_width(10); 80 81 #create a vbox that will contain all the stock buttons 82 my $vbox_stock = Gtk2::VBox->new(FALSE,5); 83 foreach my $val(sort Gtk2::Stock->list_ids){ 84 my $btn_stock = Gtk2::Button->new_from_stock($val); 85 $vbox_stock->pack_start($btn_stock,FALSE,FALSE,4); 86 } 87 #add the vbox with all the stock buttons 88 $sw->add_with_viewport($vbox_stock); 89 90 $frame->add($sw); 91 92 $vbox->pack_start($frame,TRUE,TRUE,4); 93 $vbox->show_all(); 94 return $vbox; 95 }
To create a cursor object
my $hand_cursor = Gtk2::Gdk::Cursor->new ('hand2');
To change the standard cursor as it enters the checkbutton, we connect the checkbutton's enter
signal to an anonymous sub that will change our cursor.This is a signal from Gtk2::Button
, but, since Gtk2::CheckButton
is a subclass of Gtk2::Button
, it also receives it. Remember that the set_cursor
method has to be on the widget's window
. ( Gtk2::Gdk::Window
).
$check_button->signal_connect('enter' => sub {$check_button->window->set_cursor($hand_cursor);});
To revert back we set the cursor to undef
as the pointer leaves the button.
$check_button->signal_connect('leave' => sub {$check_button->window->set_cursor(undef);});
To do something when the Gtk2::CheckButton
is checked or not, we connect to Gtk2::ToggleButton
's toggled
method and use a closure, where we can "gray out" the Gtk2::ScrolledWindow
object, and set the image and caption of the checkbutton.
$check_button->signal_connect (toggled => sub { my $self = shift; if ($self->get_active){ # 'activate' the scrolled window and chance the checkbutton's # appearance if the user checks the check button. my $img_dude = Gtk2::Image->new_from_file("./pix/sweet.jpg"); #add a touch of detail $window->set_icon_from_file ("./pix/dude.jpg"); $sw->set_sensitive (TRUE); $check_button->set_label("Sweet, and what about mine?"); $check_button->set_property('image'=>$img_dude); }else{ # 'gray out' the scrolled window and chance the checkbutton's # appearance if the user un-checks the check button. my $img_sweet = Gtk2::Image->new_from_file("./pix/dude.jpg"); #add a touch of detail $window->set_icon_from_file ("./pix/sweet.jpg"); $sw->set_sensitive (FALSE); $check_button->set_label("Dude, what does mine say?"); $check_button->set_property('image'=>$img_sweet); } });
To give your program a little personal touch, you can specify an icon to display on the window corner. This is done by |
If you want to create a buffer around a Gtk2::Container
subclass, use the set_border_width
method.
To set the minimum size of a widget, you use the Gtk2::Widget
class's set_size_request
method. This is nice to set initial sizes. We use it in our program to size the scrolled window.
$sw->set_size_request (300, 300);
To get a list of all the Gtk2::Stock
id's use the Gtk2::Stock
->list_ids
method.
foreach my $val(sort Gtk2::Stock->list_ids){ my $btn_stock = Gtk2::Button->new_from_stock($val); $vbox_stock->pack_start($btn_stock,0,0,4); }
We only want our scrolled window to scroll vertically, and not horizontally.
$sw->set_policy ('never', 'automatic');
[1] | Some widgets are "natively scrollable" -- that is, they support the If you use |