Programming with Gtk2-Perl/Signals and Callbacks

From Wikibooks, open books for an open world
Jump to navigation Jump to search

Signals

The Gtk framework is event driven. This means it will remain idle in Gtk's main loop until an event occurs, at which point a signal will be emitted. If we have connected a callback to the signal, it will be executed before returning control back to the main loop.


In the last chapter we connected to the clicked signal of a button in order save some user input to a file.

$save_btn->signal_connect('clicked' => \&save_note, $entry);

sub save_note {
    my ($save_btn, $entry) = @_;
    my $text  = $entry->get_text;
    $entry->set_text('');
 
    open my $OUTFILE, '>>notes.txt'
        or die "could not open notes.txt for appending";
    flock $OUTFILE, 2;
    print $OUTFILE join '|', time, $text . "\n";
    close $OUTFILE;
}


Signal Connect

Here is the syntax of the signal_connect method which is provided in the Glib::Object base class - which all widgets inherit from. In addition to the name of the signal and callback, you may optionally pass in a scalar to be passed to the callback function when it is executed.

$widget->signal_connect($signal_name, \&callback, [$data])


Callbacks

Callbacks are subroutine references that will be executed when a signal is emitted. When you define your callback function you will get the emitting widget and optionally a $data value as arguments.

sub callback {
    my ($widget, $data) = @_;

    #...
}


Callbacks can also be anonymous subroutines. You can then use encapsulation to avoid passing in an argument. This approach is best used for short, simple callbacks. Take the example below.

$entry = Gtk2::Entry->new;

$button->signal_connect(clicked => sub {
    print $entry->get_text, "\n";
});

Events

There also exists a set of events that you can connect callbacks to. Use the same signal_connect method in exactly the same manner as when connecting to signals. These events reflect the those of the x event mechanism. Here is a complete listing.

  • event
  • button_press_event
  • button_release_event
  • scroll_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
  • visibility_notify_event
  • client_event
  • no_expose_event
  • window_state_event


Callbacks

The callback function is slightly different for events.

sub callback_func {
    my ($widget, $event, $data) = @_;
    
    # ...
    
    return $ret;
}

The $event argument is an object that inherits from Gtk2::Gdk::Event. The actual package name will depend on the which event occurred. You can call the 'type' method on the $event to retrieve the type of event that occurred. You may also be able to call other methods on the $event that may be of interest, but that will vary depending on the type of event.


Event Types

Here is a list of possible values that could be returned from the type method.

  • 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-enter
  • drag-leave
  • drag-motion
  • drag-status
  • drop-start
  • drop-finished
  • client-event
  • visibility-notify
  • no-expose
  • scroll
  • window-state
  • setting


Return Values

The value returned from your callback function determines whether events should be propagated further. Returning a TRUE value will stop the propagation of events, while a FALSE value will continue one with normal event handling.


Disconnecting and Blocking

By storing the Integer value returned from the 'signal_connect' method, we can disconnect the callback later.

$id = $widget->signal_connect($signal => \&callback, $data );

$widget->signal_handler_disconnect($id);


You can also temporarily disable a callback from firing.

$widget->signal_handler_block($id);

$widget->signal_handlers_block_by_func(\&callback, $data);

$widget->signal_handler_unblock($id);

$widget->signal_handlers_unblock_by_func(\&callback, $data);