Gtk est une ``boîte à outils dirigée par les évènements'' ce qui signifie
qu'il veille dans main Gtk jusqu'à ce qu'un évènement se produise. Si
c'est le cas, le contrôle est alors passé à la fonction appropriée.
Ce passage de contrôle se fait en utilisant l'idée de ``signal''. Ces signaux ne sont pas les mêmes que les signaux d'un système Unix et ne sont pas implémentés en les utilisant bien que la terminologie soit presque identique. Quand quelque chose, comme `` la pression sur un bouton de souris'' se produit, le signal approprié sera émis par le widget qui fut pressé. C'est ainsi que Gtk fait la plupart de son travail utile. Il est des signaux dont tous les widgets héritent tel que ``destroy'', et d'autres qui sont spécifiques tel que le ``toggled'' signal d'un bouton ``toggle''.
Pour faire agir un bouton, nous plaçons un gestionnaire de signal qui appellera la fonction appropriée. On le fait avec des fonctions comme celles-ci :
$object->signal_connect( "signal_name", \&signal_func ); $object->signal_connect( signal_name => \&signal_func ); $object->signal_connect( "signal_name", \&signal_func, $optional_data ... ); $object->signal_connect( "signal_name", \&signal_func, @optional_data );
En Perl, les deux premières formes sont identiques ainsi que les deux suivantes car Perl envoit tous les arguments sous la forme d'une seule liste de scalaires. Bien sûr, vous pouvez envoyer autant d'éléments par liste que vous le désirez.
La variable à gauche du signal_connect() est le widget qui émettra
le signal. Le premier argument est une chaîne de caractères représentant le
signal dont vous aimeriez enregistrer le rappel de signal. Le second argument
est la routine que vous voulez appeler. Cette routine est appelée rappel de
signal. Si vous passez des arguments à la routine, vous les précisez en les
ajoutant à la fin de la liste d'arguments. Tout ce qui est après le second argument
est passé en tant que liste, c'est pourquoi vous pouvez vous permettre de passer
autant d'arguments que vous le souhaitez.
Si vous ne comprenez pas les références Perl, souvenez-vous que les routines
sont précédées par un \& et que vous ne pouvez pas placer des parenthèses
après le nom de la routine.
Pour les rappels de signaux associés avec uniquement un signal et composés de quelques lignes, il est courant de voir quelque chose comme ceci :
$object->signal_connect( "signal_name", sub { do_something; } );
Une routine est habituellement définié par :
sub callback_func
{
my ( $widget , $data ) = @_ ;
...
}
Le premier argument envoyé à un rappel de signal sera toujours le widget émetteur
et le reste des arguments sont des données optionnelles envoyées par la fonction
signal_connect() . Souvenez-vous que Perl ne vous oblige pas à déclarer
ou à utiliser les arguments envoyés à une routine.
Noter que la forme ci-dessus pour une fonction de rappel de signal est uniquement
un guide général et que certains signaux spécifiques à certains widgets génèrent
différents paramètres appelants. Par exemple, le signal Clist select row
fournit à la fois les paramètres de ligne et de colonne.
En plus du mécanisme des signaux décrit précédemment, il y a un ensemble d'évènements qui reflètent les mécanismes des évènements X. Les rappels signaux peuvent également être attaché à ces évènements qui sont :
event button_press_even button_release_event motion_notify_event delete_event destroy_event expose_event key_press_event key_release_event enter_notify_event leave_notify_event configure_event focus_in_event focus_out_event map_event unmap_event property_notify_event selection_clear_event selection_request_event selection_notify_event proximity_in_event proximity_out_event drag_begin_event drag_request_event drag_end_event drop_enter_event drop_leave_event drop_data_available_event other_event
Afin de connecter une fonction de rappel à l'un de ces évènements, on utilise
signal_connect() comme on la connecterait à un signal en utilisant
seulement l'un des noms d'évènements à la place du nom du signal. Le dernier
argument passé au rappel de signal est une structure d'évènement ainsi au début
de votre fonction, vous devriez dire :
my ( $widget, $data, $event ) = @_;
ou si vous voulez passer un ensemble de données :
my ( $widget, @data ) = @_; my $event = pop( @data );
Les domaines les plus courants dans les structures d'évènements sont les ``boutons'', ``les touches'' et ``type''. Le domaine des boutons contient un nombre avec le bouton pressé ( typiquement 1, 2 ou 3 ). Le domaine `` touche'' contient la touche pressée ( s'il y en a une ). Le domaine ``type'' contient l'une des chaînes suivantes :
'nothing' 'delete' 'destroy' 'expose' 'motion_notify' 'button_press' '2button_press' '3button_press' 'button_release' 'key_press' 'key_release' 'enter_notify' 'leave_notify' 'focus_change' 'configure' 'map' 'unmap' 'property_notify' 'selection_clear' 'selection_request' 'selection_notify' 'proximity_in' 'proximity_out' 'drag_begin' 'drag_request' 'drop_enter' 'drop_leave' 'drop_data_avail' 'cLIent_event' 'visibiLIty_notify' 'no_expose'
Cela permet de déterminer facilement la cause d'un évènement. Par exemple, cela fut-il causé par un bouton pressé ? si oui, lequel ?
sub some_event
{
my ( $widget, @data ) = @_;
my $event = pop( @data );
if ( ( defined( $event->{'type'} ) )
and ( $event->{'type'} eq 'button_press' ) )
{
if ( $event->{'button'} == 3 )
{
# right click
}
else
{
# non-right click
}
}
}
Gardez à l'esprit que le code précédent ne fonctionne que si le rappel est lié à l'un des évènements mentionnés ci-dessus. Les signaux n'envoient pas une structure d'évènement ainsi, à moins que vous ne connaissiez exactement le nombre d'arguments envoyés, vous n'avez pas besoin de l'information sur la structure d'un évènement. Je milite pour ne pas connecter un signal et un évènement au même retour.
La valeur de retour de la fonction signal_connect() est un ``tag''
qui identifie la fonction de rappel. Vous pouvez avoir autant de rappels par
signal ou par objet que vous le souhaitez et ils seront exécutés les uns après
les autres dans l'ordre ou ils ont été attaché.
Si vous voulez émettre un signal spécifique, vous pouvez le faire en appelant l'une des fonctions suivantes :
$widget->signal_emit( $id ); $widget->signal_emit_by_name( $signal_name );
L'argument de la première forme est le ``id tag'' qui est retourné par signal_connect() .
L'argument de la seconde forme est une chaîne identifiant le nom du signal ?
Ainsi beaucoup de widgets ont des fonctions qui émettent des signaux les plus
courants. Par exemple, la fonction destroy() permettra au signal 'destroy'
d'être émis et la fonction activate () permettra au signal 'activate'
d'être émis.
Ce ``id tag'' vous permet également de supprimer un retour de la liste en
utilisant signal_disconnect() comme ceci :
$widget->signal_disconnect( $id );
Si vous voulez ôter tous les gestionnaires d'un widget, vous pouvez appeler la fonction :
$widget->signal_handlers_destroy();
Cet appel se passe de commentaires. Il enlève simplement tous les gestionnaires de l'objet passé en tant que premier argument.
Vous pouvez débrancher temporairement des gestionnaires avec :
$widget->signal_handler_block( $callback_id ); $widget->signal_handler_block_by_func( \&callback, $data ); $widget->signal_handler_block_by_data( $data ); $widget->signal_handler_unblock( $callback_id ); $widget->signal_handler_unblock_by_func( \&callback, $data ); $widget->signal_handler_unblock_by_data( $data );
Voici un aperçu des fonctions utilisées pour connecter ou déconnecter un gestionnaire
pour chacun des signal_connect disponibles. Vous trouverez plus de détails
dans la documentation Gtk.
$id = $object->signal_connect( $signal_name, \&function, @optional_data ); $id = $object->signal_connect_after( $signal_name, \&function, @optional_data ); $id = $object->signal_connect_object( $signal_name, \&function, $slot_object ); $id = $object->signal_connect_object_after( $signal_name, \&function, $slot_object ); # Je ne suis pas sûr de celle-là $id = $object->signal_connect_full( $name, \&function, $callback_marshal, @optional_data, \&destroy_function, $object_signal, $after ); # Je ne suis pas sûr de celle-là non plus $id = $object->signal_connect_interp( $name, \&function, @optional_data, \&destroy_function, $after ); $id = $object->signal_connect_object_while_alive( $signal, \&function, $alive_object ); $id = $object->signal_connect_while_alive( $signal, \&function, @optional_data, $alive_object ); $object->signal_disconnect( $id ); $object->signal_disconnect_by_func( \&;function, @optional_data );
L'émission d'un signal est un processus par lequel Gtk fait fonctionner tous
les gestionnaires pour un objet et un signal spécifique. Premièrement, sachez
que la valeur de retour de l'émission est la valeur du dernier gestionnaire
utilisé. Puisque tous les signaux d'évènements sont du type `` last'', ce
sera le gestionnaire par défaut, à moins que vous ne les connectiez avec les
signal signal_connect_after() .
La manière dont un évènement est pris en charge est :
La valeur de retour d'un gestionnaire n'aura aucun effet s'il y a un gestionnaire
par défaut, à moins que vous ne connectiez avec signal_connect_after() .
Pour empêcher le gestionnaire par défaut de se déclencher, vous avez besoin
de connecter avec signal_connect() et d'utiliser signal_emit_stop_by_name() .
La valeur de retour affecte seulement si le signal est propagé et pas l'émission
courante.