Chapitre 16
Les boutons spin

Les boutons spins sont généralement utilisés pour permettre à l’utilisateur de sélectionner une valeur dans un intervalle de valeurs. Ils consistent en une boite d’entrée texte avec des boutons flèches attachés sur le côté. Cliquer sur l’un des boutons fait varier la valeur sur l’échelle des valeurs disponibles. La boîte entrée peut aussi être éditée directement pour entrer une valeur spécifique.

Le bouton spin permet à la valeur d’être entière ou avec un certain de décimales et d’être incrémentée/décrémentée selon des valeurs configurables. L’action de maintenir un bouton enfoncé peut, optionnellement, se traduire par une accélération de la variation de la valeur en fonction de la durée de la pression.

Le bouton spin utilise les ajustements pour prendre des informations à propos de l’échelle des valeurs que le bouton peut prendre. Rappelez vous que le widget ajustement est créé par la fonction suivante et qui montre les informations qu’elle prend en compte :

$adj = Gtk2::Adjustment->new( $value,  
                            $lower,  
                            $upper,  
                            $step_increment,  
                            $page_increment,  
                            $page_size );
Les attributs de l’ajustement sont utilisés par les boutons spin sont :

En plus, le bouton 3 de la souris peut être utilisé pour sauter directement à la valeur $upper ou $lower quand on l’utilise pour sélectionner l’un des boutons.

Créer un bouton spin

$spin = Gtk2::SpinButton->new( $adjustment, $climb_rate, $digits );
L’argument  $climb_rate prend une valeur entre 0.0 et 1.0 et indique la quantité d’accélération du bouton spin. L’argument  $digits spécifie le nombre de décimales que la valeur peut prendre.

Configuration

Un bouton spin peut être reconfiguré après sa création avec :

$spin->configure( $adjustment, $climb_rate, $digits );
L’ajustement peut être réglé et retrouvé indépendamment un utilisant les deux fonctions :
$spin->set_adjustment( $adjustment );  
$spin->get_adjustment();
Le nombre de décimales peut être changé par :
$spin->set_digits( $digits );

Valeur

La valeur que le bouton spin est en train d’afficher peut être changée par :

$spin->set_value( $value );
La valeur du bouton spin peut être retrouvée sous la forme d’un nombre décimal ou d’un entier à l’aide de :
$spin->get_value();  
$spin->get_value_as_int();
Si vous voulez changer la valeur du bouton spin
$spin->spin( $direction, $increment );

Le paramètre $direction peut prendre les valeurs :

Comportement

Laissons maintenant les fonctions de réglage et de récupération pour nous intéresser aux fonctions qui agissent sur l’apparence et sur le comportement du bouton spin.

La première de ces fonctions est utilisée pour contraindre la boîte texte du bouton à ne contenir qu’une valeur numérique. Cela empêche l’utilisateur de taper autre chose qu’une valeur numérique.

$spin->set_numeric( $numeric );
Vous pouvez indiquer si le bouton est compris entre la valeur la plus basse et la plus haute.
$spin->set_wrap( $wrap );
Vous pouvez obliger le bouton à arrondir la valeur au plus proche step_increment qui est déclarée à l’intérieur de l’objet ajustement utilisé par le bouton spin :
$spin->set_snap_to_ticks( $snap_to_ticks );
Le comportement du bouton peut être modifié par :
$spin->set_update_policy( $policy );
Les valeurs possibles de $policy sont soit 'always' soit 'if_valid'. Ces valeurs affectent le comportement du bouton quand l’utilisateur écrit la valeur. Dans le cas de 'if_valid', la valeur du bouton spin ne change que si le texte d’entrée est une valeur numérique comprise entre les valeurs spécifiées par l’ajustement. Autrement le texte est effacé et remplacé par la valeur courante. Dans le cas de 'update_always', on ignore les erreurs en convertissant le texte en valeur numérique.

Exemple

spin

# !/usr/bin/perl -w

use Gtk2 ’-init’ ;
# Variables convenables pour vrai et faux
use constant TRUE => 1 ;
use constant FALSE => 0 ;

use strict ;

my $window = Gtk2::Window->new( ”toplevel” ) ;
$window->signal_connect( ”destroy” , sub { Gtk2->main_quit ; } ) ;
$window->set_title( ”Les boutons Spin” ) ;

my $main_vbox = Gtk2::VBox->new( FALSE, 5 ) ;
$main_vbox->set_border_width( 10 ) ;
$window->add( $main_vbox ) ;

# Un cadre dans lequel on place une boîte verticale
my $frame = Gtk2::Frame->new( ”Pas accéleré” ) ;
$main_vbox->pack_start( $frame, TRUE, TRUE, 0 ) ;
my $vbox1 = new Gtk2::VBox( FALSE, 0 ) ;
$vbox1->set_border_width( 5 ) ;
$frame->add( $vbox1 ) ;

# Une boîte horizontale pour placer nos trois boutons spins
my $hbox1 = Gtk2::HBox->new( FALSE, 0 ) ;
$vbox1->pack_start( $hbox1, TRUE, TRUE, 5 ) ;

# Création d’une boîte verticale dans lequel on place le label
# puis le bouton spin
my $vbox2 = Gtk2::VBox->new( FALSE, 0 ) ;
$hbox1->pack_start( $vbox2, TRUE, TRUE, 5 ) ;
my $label1 = Gtk2::Label->new( ”Jour :” ) ;
$label1->set_alignment( 0 , 0.5 ) ;
$vbox2->pack_start( $label1, FALSE, TRUE, 0 ) ;
my $adj = Gtk2::Adjustment->new( 1.0 , 1.0 , 31.0 , 1.0 , 5.0 , 0.0 ) ;
my $spinner1 = Gtk2::SpinButton->new( $adj, 0 , 0 ) ;
$spinner1->set_wrap( TRUE ) ;
$vbox2->pack_start( $spinner1, FALSE, TRUE, 0 ) ;

# idem
my $vbox3 = Gtk2::VBox->new( FALSE, 0 ) ;
$hbox1->pack_start( $vbox3, TRUE, TRUE, 5 ) ;
my $label2 = Gtk2::Label->new( ”Mois :” ) ;
$label2->set_alignment( 0 , 0.5 ) ;
$vbox3->pack_start( $label2, FALSE, TRUE, 0 ) ;
my $adj2 = Gtk2::Adjustment->new( 1.0 , 1.0 , 12.0 , 1.0 , 5.0 , 0.0 ) ;
my $spinner2 = Gtk2::SpinButton->new( $adj2, 0 , 0 ) ;
$spinner2->set_wrap( TRUE ) ;
$vbox3->pack_start( $spinner2, FALSE, TRUE, 0 ) ;

# idem
my $vbox4 = Gtk2::VBox->new( FALSE, 0 ) ;
$hbox1->pack_start( $vbox4, TRUE, TRUE, 5 ) ;
my $label3 = Gtk2::Label->new( ”Année :” ) ;
$label3->set_alignment( 0 , 0.5 ) ;
$vbox4->pack_start( $label3, FALSE, TRUE, 0 ) ;
my $adj3 = Gtk2::Adjustment->new( 1998.0 , 0.0 , 2100.0 , 1.0 , 100.0 , 0.0 ) ;
my $spinner3 = Gtk2::SpinButton->new( $adj3, 0 , 0 ) ;
$spinner3->set_wrap( FALSE ) ;
$vbox4->pack_start( $spinner3, FALSE, TRUE, 0 ) ;

# Second cadre avec également une boite verticale
my $frame2 = Gtk2::Frame->new( ”Accéleré” ) ;
$main_vbox->pack_start( $frame2, TRUE, TRUE, 0 ) ;
my $vbox5 = Gtk2::VBox->new( FALSE, 0 ) ;
$vbox5->set_border_width( 5 ) ;
$frame2->add( $vbox5 ) ;

# même technique que précédemment
my $hbox2 = Gtk2::HBox->new( FALSE, 0 ) ;
$vbox5->pack_start( $hbox2, FALSE, TRUE, 5 ) ;

# idem
my $vbox6 = Gtk2::VBox->new( FALSE, 0 ) ;
$hbox2->pack_start( $vbox6, TRUE, TRUE, 5 ) ;
my $label4 = Gtk2::Label->new( ”Valeur: ” ) ;
$label4->set_alignment( 0 , 0.5 ) ;
$vbox6->pack_start( $label4, FALSE, TRUE, 0 ) ;
my $adj4 = Gtk2::Adjustment->new( 0.0 , -10000.0 , 10000.0 , 0.1 , 100.0 , 0.0 ) ;
my $spinner4 = Gtk2::SpinButton->new( $adj4, 1.0 , 2 ) ;
$spinner4->set_wrap( TRUE ) ;
$vbox6->pack_start( $spinner4, FALSE, TRUE, 0 ) ;

# idem
my $vbox7 = Gtk2::VBox->new( FALSE, 0 ) ;
$hbox2->pack_start( $vbox7, TRUE, TRUE, 5 ) ;
my $label5 = Gtk2::Label->new( ”Décimales :” ) ;
$label5->set_alignment( 0 , 0.5 ) ;
$vbox7->pack_start( $label5, FALSE, TRUE, 0 ) ;
my $adj5 = Gtk2::Adjustment->new( 2 , 1 , 5 , 1 , 1 , 0 ) ;
my $spinner5 = Gtk2::SpinButton->new( $adj5, 0.0 , 0 ) ;
$spinner5->set_wrap( TRUE ) ;
$adj5->signal_connect( ”value_changed” , \&change_digits, $spinner4 ) ;
$vbox7->pack_start( $spinner5, FALSE, TRUE, 0 ) ;

# Les cases à cocher pour changer les propriétés du bouton $spinner4
my $hbox3 = Gtk2::HBox->new( FALSE, 0 ) ;
$vbox7->pack_start( $hbox3, FALSE, TRUE, 5 ) ;
my $button1 = Gtk2::CheckButton->new( ”Arrondi à l’incrément près” ) ;
$button1->signal_connect( ”clicked” , \&toggle_snap, $spinner4 ) ;
$vbox5->pack_start( $button1, TRUE, TRUE, 0 ) ;
$button1->set_active( TRUE ) ;

# idem
my $button2 = Gtk2::CheckButton->new( ”Entrée uniquement numérique” ) ;
$button2->signal_connect( ”clicked” , \&toggle_numeric, $spinner4 ) ;
$vbox5->pack_start( $button2, TRUE, TRUE, 0 ) ;
$button2->set_active( TRUE ) ;

# Les boutons qui déclenchent la lecture du contenu du bouton $spinner4
my $hbox4 = Gtk2::HBox->new( FALSE, 0 ) ;
$vbox5->pack_start( $hbox4, FALSE, TRUE, 5 ) ;

my $button3 = Gtk2::Button->new( ”Valeur entière” ) ;
$button3->signal_connect(’clicked’ ,\&get_value,1 ) ;
$hbox4->pack_start( $button3, TRUE, TRUE, 5 ) ;

my $button4 = Gtk2::Button->new( ”Valeur décimale” ) ;
$button4->signal_connect( ”clicked” , \&get_value,2 ) ;
$hbox4->pack_start( $button4, TRUE, TRUE, 5 ) ;

# Le label pour afficher la valeur retenue
my $val_label = Gtk2::Label->new( ”0” ) ;
$vbox5->pack_start( $val_label, TRUE, TRUE, 0 ) ;

# Le bouton pour quitter
my $button5 = Gtk2::Button->new_from_stock( ’gtk-close’ ) ;
$button5->signal_connect( ”clicked” , sub { Gtk2->main_quit ; } ) ;
$main_vbox->pack_start( $button5, TRUE, TRUE, 5 ) ;

$window->show_all() ;

Gtk2->main ;

### Routines
sub toggle_snap {
my ( $widget, $spin ) = @_ ;
$spin->set_snap_to_ticks( $widget->get_active ) ;
}

sub toggle_numeric {
my ( $widget, $spin ) = @_ ;
$spin->set_numeric( $widget->get_active ) ;
}

sub change_digits {
my ( $widget, $spin ) = @_ ;
$spin->set_digits( $spinner5->get_value_as_int() ) ;
}

sub get_value {
my ( $widget, $num) = @_ ;
my $buf = ”” ;
if ( $num == 1 )
{
$buf = $spinner4->get_value_as_int() ;
}
else
{
$buf = $spinner4->get_value() ;
}
$val_label->set_text( $buf ) ;
}