? 在 2.0 版,信號系統(tǒng)已從 GTK 移到 GLib,因此在函數(shù)和類型的說明中有前綴 “g_” 而不是 “gtk_”。
GTK 是一個事件驅動的工具包,意味著它會等在gtk_main() 那里, 直到下一個事件發(fā)生, 才把控制權傳給適當 的函數(shù)??刂茩嗟膫鬟f是使用“信號”的辦法來完成的。(注意這里的信號并不等同于Unix 系統(tǒng)里的信號,并且也不是用它們實現(xiàn)的,雖然使用的術語是一樣的。)
1.常用信號
??構件能夠發(fā)送各種信號,信號可以由用戶操作而引起,也可以由函數(shù)模擬事件產(chǎn)生,常見信號如下。
構件 | 信號 | 意義 | 產(chǎn)生信號函數(shù) |
windows | “destroy” | 關閉窗口時發(fā)出該信號 | |
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信號,當將要關閉窗口時,出現(xiàn)delete_event事件。當關閉窗口時,發(fā)出destroy信號。對于delete_event事件,頂層窗口應該設有相應的回呼函數(shù)。因為delete_event表示用戶需要關閉應用軟件。對于delete_event信號增加回呼函數(shù)包括兩個步驟。
delete_event的回呼函數(shù)應該返回布爾值,用以表示是否允許關閉窗口。返回TRUR值保持窗口打開,返回FALSE值表示窗口可以關閉。如果關閉窗口,接著發(fā)出destroy信號告訴應用程序就要關閉窗口。
2.信號連接和處理函數(shù)
2.1 信號連接函數(shù) g_signal_connect
??每個信號和每個對象可以有多個回調函數(shù),并且它們會按設置的順序依次運行。
/* 信號連接函數(shù)*/ #define g_signal_connect(instance, detailed_signal, c_handler, data) 形參:instance --void*指針,要發(fā)出信號的構件 detailed_signal -- char *指針,連接的信號的名稱 c_handler --信號被捕獲時所要調用的函數(shù) data -- void*指針,傳遞給信號處理函數(shù)(回調函數(shù))的數(shù)據(jù) 返回值:gulong類型,返回識別回調函數(shù)的標識 第三個參數(shù)即回調函數(shù)一般形式如下: void callback_func( GtkWidget *widget,gpointer callback_data ); 形參:widget -- 指向發(fā)出信號的構件的指針 callback_data --g_signal_connect傳入的參數(shù) 注意:上面回調函數(shù)的聲明只是一般的形式, 有些構件的特殊信號會用不同的調用參數(shù)。
2.2 g_signal_connect返回值
信號連接函數(shù)g_signal_connect返回值為glong類型,返回一個識別回調函數(shù)的標志。因為每個信號和每個對象可以有多個回調函數(shù),并且它們會按設置的順序依次運行。所以可以通過這個返回標志,可通過下面函數(shù)將實現(xiàn)的回調函數(shù)刪除:
g_signal_handler_disconnect(gpointer instance, gulong handler_id)
?所以,通過傳遞你想在上面刪除處理函數(shù)的構件,以及某個signal_connect函數(shù)返回的標識,你就可以中斷一個信號處理函數(shù)的連接。
也可以使用g_signal_handler_block() 和 g_signal_handler_unblock() 這類函數(shù)來暫時斷開信號處理函數(shù)的連接。
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 信號連接函數(shù) g_signal_connect_swapped
/*信號連接函數(shù)*/ #define g_signal_connect_swapped(instance, detailed_signal, c_handler, data) g_signal_connect_swapped()和g_signal_connect() 相同,只是回調函數(shù)只用一個參數(shù),一個指向GTK對象的指針。所以當使用這個函數(shù)連接信號時,回調函數(shù)應該是這樣的形式: void callback_func( GtkObject *object );
??擁有兩個函數(shù)來設置信號連接的目的只是為了允許回調函數(shù)有不同數(shù)目的參數(shù)。GTK 庫中許多函數(shù)僅接受一個單獨的構件指針作為其參數(shù),所以對于這些函數(shù)你要用 g_signal_connect_swapped(),然而對你自己定義的函數(shù),你可能需要附加的數(shù)據(jù)提供給你的回調函數(shù)。
3 事件
??除有信號機制外,還有一套 events 反映 X 事件機制?;卣{函數(shù)可以與這些事件連接。
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
??所以, 連接一個回調函數(shù)到這些事件之一,我們會這樣用:
g_signal_connect (G_OBJECT (button), "button_press_event",G_CALLBACK (button_press_callback), NULL);
??這里假定button是一個按鈕構件?,F(xiàn)在,當鼠標位于按鈕上并按一下鼠標時,函數(shù) button_press_callback() 會被調用。這個函數(shù)應該聲明為:
static gint button_press_callback( GtkWidget *widget, GdkEventButton *event, gpointer data );
?注意,我們可以把第二個參數(shù)類型聲明為 GdkEventButton,因為我們知道哪個類型的事件會發(fā)生。
這個函數(shù)的返回值指示這個事件是否應該由 GTK 事件處理機制做進一步的傳播。 返回 TRUE 指示這個事件已經(jīng)處理了,且不應該做進一步傳播。 返回 FALSE 繼續(xù)正常的事件處理。
3.1 按鍵連接信號關閉窗口示例
#include void hello(GtkWidget *widget,gpointer data) { g_print("按鍵信號觸發(fā)成功n"); } /*事件處理回調函數(shù)*/ gint delete_event(GtkWidget *widget,GdkEvent *evnet,gpointer data) { g_print("事件處理回調函數(shù)調用成功n"); return TRUE;//TRUE表示繼續(xù),F(xiàn)ALSE表示關閉 } 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); /*創(chuàng)建窗口*/ window=gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window),"GTK");/*設置窗口標題*/ /*信號連接函數(shù)*/ 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); /*創(chuàng)建新的按鈕,設置按鈕信息為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按鈕,按鍵發(fā)出clicked信號,觸發(fā)hello回調函數(shù),接著調用下一個信號處理函數(shù)gtk_widget_destroy(),將窗口構件參數(shù)傳遞給該函數(shù),銷毀窗口,從而窗口發(fā)出destroy信號,然后調用我們實現(xiàn)號的回調函數(shù)destroy(),實現(xiàn)程序退出。
審核編輯:湯梓紅
-
信號
+關注
關注
11文章
2773瀏覽量
76541 -
回調函數(shù)
+關注
關注
0文章
87瀏覽量
11529
發(fā)布評論請先 登錄
相關推薦
評論