跳转到内容

使用 Gtk2-Perl/Signals 和 Callbacks 进行编程

来自维基教科书,开放世界中的开放书籍

Gtk 框架是事件驱动的。这意味着它将在 Gtk 的主循环中保持空闲,直到发生事件,此时将发出一个信号。如果我们已将回调连接到信号,它将在将控制权返回主循环之前执行。


在上一章中,我们连接到按钮的 clicked 信号以将一些用户输入保存到文件中。

$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;
}


信号连接

[编辑 | 编辑源代码]

以下是 Glib::Object 基类中提供的 signal_connect 方法的语法 - 所有小部件都继承自它。除了信号和回调的名称之外,您还可以选择传递一个标量,当回调函数执行时将其传递给回调函数。

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


回调是子例程引用,当发出信号时将执行。当您定义回调函数时,您将获得发出小部件和可选的 $data 值作为参数。

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

    #...
}


回调也可以是匿名子例程。然后,您可以使用封装来避免传入参数。这种方法最适合简短简单的回调。请看下面的例子。

$entry = Gtk2::Entry->new;

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

还存在一组事件,您可以将回调连接到这些事件。以与连接到信号完全相同的方式使用相同的 signal_connect 方法。这些事件反映了 x 事件机制的那些事件。以下是完整的列表。

  • 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


回调函数对于事件略有不同。

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

$event 参数是一个继承自 Gtk2::Gdk::Event 的对象。实际的包名称将取决于发生了哪个事件。您可以对 $event 调用 'type' 方法来检索发生的事件类型。您还可以对 $event 调用其他可能感兴趣的方法,但这将根据事件类型而有所不同。


事件类型

[编辑 | 编辑源代码]

以下列出了 type 方法可能返回的可能值。

  • 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


返回值

[编辑 | 编辑源代码]

从回调函数返回的值决定事件是否应进一步传播。返回 TRUE 值将停止事件传播,而 FALSE 值将继续进行正常的事件处理。


断开连接和阻塞

[编辑 | 编辑源代码]

通过存储从 'signal_connect' 方法返回的 Integer 值,我们可以在以后断开回调连接。

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

$widget->signal_handler_disconnect($id);


您还可以暂时禁用回调的触发。

$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);
华夏公益教科书