跳轉到內容

使用 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);
華夏公益教科書