? 在 2.0 版,信號系統已從 GTK 移到 GLib,因此在函數和類型的說明中有前綴 “g_” 而不是 “gtk_”。
GTK 是一個事件驅動的工具包,意味著它會等在gtk_main() 那里, 直到下一個事件發生, 才把控制權傳給適當 的函數。控制權的傳遞是使用“信號”的辦法來完成的。(注意這里的信號并不等同于Unix 系統里的信號,并且也不是用它們實現的,雖然使用的術語是一樣的。)
1.常用信號
??構件能夠發送各種信號,信號可以由用戶操作而引起,也可以由函數模擬事件產生,常見信號如下。
構件 | 信號 | 意義 | 產生信號函數 |
windows | “destroy” | 關閉窗口時發出該信號 | |
button | “clicked” | 點擊按鈕,這是按下和釋放操作的組合 | gtk_button_clicked(button) |
“clicked” | 點擊按鈕,這是按下和釋放操作的組合 | gtk_button_clicked(button) | |
“clicked” | 點擊按鈕,這是按下和釋放操作的組合 | gtk_button_clicked(button) | |
“pressed” | 按下按鈕 | gtk_button_pressed(button) | |
“released” | 釋放按鈕 | gtk_button_released(button) | |
toggle_button | “toggled” | 開關按鈕 | |
listbox | “select” | 列表框被選擇 | |
“selection_changed” | 列表框選擇被更改 | ||
GTKRadioMenuItem | “activate” | 菜單選項被選擇 |
? GTK+的兩個基本機制是delete_event事件和destroy信號,當將要關閉窗口時,出現delete_event事件。當關閉窗口時,發出destroy信號。對于delete_event事件,頂層窗口應該設有相應的回呼函數。因為delete_event表示用戶需要關閉應用軟件。對于delete_event信號增加回呼函數包括兩個步驟。
delete_event的回呼函數應該返回布爾值,用以表示是否允許關閉窗口。返回TRUR值保持窗口打開,返回FALSE值表示窗口可以關閉。如果關閉窗口,接著發出destroy信號告訴應用程序就要關閉窗口。
2.信號連接和處理函數
2.1 信號連接函數 g_signal_connect
??每個信號和每個對象可以有多個回調函數,并且它們會按設置的順序依次運行。
/* 信號連接函數*/ #define g_signal_connect(instance, detailed_signal, c_handler, data) 形參:instance --void*指針,要發出信號的構件 detailed_signal -- char *指針,連接的信號的名稱 c_handler --信號被捕獲時所要調用的函數 data -- void*指針,傳遞給信號處理函數(回調函數)的數據 返回值:gulong類型,返回識別回調函數的標識 第三個參數即回調函數一般形式如下: void callback_func( GtkWidget *widget,gpointer callback_data ); 形參:widget -- 指向發出信號的構件的指針 callback_data --g_signal_connect傳入的參數 注意:上面回調函數的聲明只是一般的形式, 有些構件的特殊信號會用不同的調用參數。
2.2 g_signal_connect返回值
信號連接函數g_signal_connect返回值為glong類型,返回一個識別回調函數的標志。因為每個信號和每個對象可以有多個回調函數,并且它們會按設置的順序依次運行。所以可以通過這個返回標志,可通過下面函數將實現的回調函數刪除:
g_signal_handler_disconnect(gpointer instance, gulong handler_id)
?所以,通過傳遞你想在上面刪除處理函數的構件,以及某個signal_connect函數返回的標識,你就可以中斷一個信號處理函數的連接。
也可以使用g_signal_handler_block() 和 g_signal_handler_unblock() 這類函數來暫時斷開信號處理函數的連接。
void g_signal_handler_block (gpointer instance, gulong handler_id); void g_signal_handlers_block_by_func( gpointer object,GCallback func,gpointer data ); void g_signal_handler_unblock (gpointer instance,gulong handler_id); void g_signal_handlers_unblock_by_func( gpointer object,GCallback func,gpointer data );
2.3 信號連接函數 g_signal_connect_swapped
/*信號連接函數*/ #define g_signal_connect_swapped(instance, detailed_signal, c_handler, data) g_signal_connect_swapped()和g_signal_connect() 相同,只是回調函數只用一個參數,一個指向GTK對象的指針。所以當使用這個函數連接信號時,回調函數應該是這樣的形式: void callback_func( GtkObject *object );
??擁有兩個函數來設置信號連接的目的只是為了允許回調函數有不同數目的參數。GTK 庫中許多函數僅接受一個單獨的構件指針作為其參數,所以對于這些函數你要用 g_signal_connect_swapped(),然而對你自己定義的函數,你可能需要附加的數據提供給你的回調函數。
3 事件
??除有信號機制外,還有一套 events 反映 X 事件機制。回調函數可以與這些事件連接。
GDK_NOTHING GDK_DELETE GDK_DESTROY GDK_EXPOSE GDK_MOTION_NOTIFY GDK_BUTTON_PRESS GDK_2BUTTON_PRESS GDK_3BUTTON_PRESS GDK_BUTTON_RELEASE GDK_KEY_PRESS GDK_KEY_RELEASE GDK_ENTER_NOTIFY GDK_LEAVE_NOTIFY GDK_FOCUS_CHANGE GDK_CONFIGURE GDK_MAP GDK_UNMAP GDK_PROPERTY_NOTIFY GDK_SELECTION_CLEAR GDK_SELECTION_REQUEST GDK_SELECTION_NOTIFY GDK_PROXIMITY_IN GDK_PROXIMITY_OUT GDK_DRAG_ENTER GDK_DRAG_LEAVE GDK_DRAG_MOTION GDK_DRAG_STATUS GDK_DROP_START GDK_DROP_FINISHED GDK_CLIENT_EVENT GDK_VISIBILITY_NOTIFY GDK_NO_EXPOSE GDK_SCROLL GDK_WINDOW_STATE GDK_SETTING
??所以, 連接一個回調函數到這些事件之一,我們會這樣用:
g_signal_connect (G_OBJECT (button), "button_press_event",G_CALLBACK (button_press_callback), NULL);
??這里假定button是一個按鈕構件。現在,當鼠標位于按鈕上并按一下鼠標時,函數 button_press_callback() 會被調用。這個函數應該聲明為:
static gint button_press_callback( GtkWidget *widget, GdkEventButton *event, gpointer data );
?注意,我們可以把第二個參數類型聲明為 GdkEventButton,因為我們知道哪個類型的事件會發生。
這個函數的返回值指示這個事件是否應該由 GTK 事件處理機制做進一步的傳播。 返回 TRUE 指示這個事件已經處理了,且不應該做進一步傳播。 返回 FALSE 繼續正常的事件處理。
3.1 按鍵連接信號關閉窗口示例
#include void hello(GtkWidget *widget,gpointer data) { g_print("按鍵信號觸發成功n"); } /*事件處理回調函數*/ gint delete_event(GtkWidget *widget,GdkEvent *evnet,gpointer data) { g_print("事件處理回調函數調用成功n"); return TRUE;//TRUE表示繼續,FALSE表示關閉 } void destroy(GtkWidget *widget,gpointer data) { g_print("銷毀窗口n"); gtk_main_quit();//退出程序 } int main(int argc,char *argv[]) { GtkWidget *window; GtkWidget *button; /*gtk初始化*/ gtk_init(&argc, &argv); /*創建窗口*/ window=gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window),"GTK");/*設置窗口標題*/ /*信號連接函數*/ g_signal_connect(GTK_OBJECT(window),"delete_event",G_CALLBACK(delete_event),NULL); g_signal_connect(GTK_OBJECT(window),"destroy", G_CALLBACK(destroy), NULL); /*設置容器對象屬性:設置窗口邊框寬度為100*/ gtk_container_set_border_width(GTK_CONTAINER(window),100); /*創建新的按鈕,設置按鈕信息為hello*/ button=gtk_button_new_with_label("hello"); g_signal_connect(GTK_OBJECT(button),"clicked",G_CALLBACK(hello),NULL); g_signal_connect_swapped(GTK_OBJECT(button),"clicked",G_CALLBACK(gtk_widget_destroy),GTK_OBJECT(window)); /*將按鈕放入窗口中*/ gtk_container_add(GTK_CONTAINER(window),button); /*顯示控件*/ gtk_widget_show_all(window); /*等待事件*/ gtk_main(); return 0; }
程序運行效果:
當我們用鼠標按下hello按鈕,按鍵發出clicked信號,觸發hello回調函數,接著調用下一個信號處理函數gtk_widget_destroy(),將窗口構件參數傳遞給該函數,銷毀窗口,從而窗口發出destroy信號,然后調用我們實現號的回調函數destroy(),實現程序退出。
審核編輯:湯梓紅
-
信號
+關注
關注
11文章
2789瀏覽量
76730 -
回調函數
+關注
關注
0文章
87瀏覽量
11554
發布評論請先 登錄
相關推薦
評論