? 在 2.0 版,信號(hào)系統(tǒng)已從 GTK 移到 GLib,因此在函數(shù)和類型的說(shuō)明中有前綴 “g_” 而不是 “gtk_”。
GTK 是一個(gè)事件驅(qū)動(dòng)的工具包,意味著它會(huì)等在gtk_main() 那里, 直到下一個(gè)事件發(fā)生, 才把控制權(quán)傳給適當(dāng) 的函數(shù)。控制權(quán)的傳遞是使用“信號(hào)”的辦法來(lái)完成的。(注意這里的信號(hào)并不等同于Unix 系統(tǒng)里的信號(hào),并且也不是用它們實(shí)現(xiàn)的,雖然使用的術(shù)語(yǔ)是一樣的。)
1.常用信號(hào)
??構(gòu)件能夠發(fā)送各種信號(hào),信號(hào)可以由用戶操作而引起,也可以由函數(shù)模擬事件產(chǎn)生,常見(jiàn)信號(hào)如下。
構(gòu)件 | 信號(hào) | 意義 | 產(chǎn)生信號(hào)函數(shù) |
windows | “destroy” | 關(guān)閉窗口時(shí)發(fā)出該信號(hào) | |
button | “clicked” | 點(diǎn)擊按鈕,這是按下和釋放操作的組合 | gtk_button_clicked(button) |
“clicked” | 點(diǎn)擊按鈕,這是按下和釋放操作的組合 | gtk_button_clicked(button) | |
“clicked” | 點(diǎn)擊按鈕,這是按下和釋放操作的組合 | gtk_button_clicked(button) | |
“pressed” | 按下按鈕 | gtk_button_pressed(button) | |
“released” | 釋放按鈕 | gtk_button_released(button) | |
toggle_button | “toggled” | 開(kāi)關(guān)按鈕 | |
listbox | “select” | 列表框被選擇 | |
“selection_changed” | 列表框選擇被更改 | ||
GTKRadioMenuItem | “activate” | 菜單選項(xiàng)被選擇 |
? GTK+的兩個(gè)基本機(jī)制是delete_event事件和destroy信號(hào),當(dāng)將要關(guān)閉窗口時(shí),出現(xiàn)delete_event事件。當(dāng)關(guān)閉窗口時(shí),發(fā)出destroy信號(hào)。對(duì)于delete_event事件,頂層窗口應(yīng)該設(shè)有相應(yīng)的回呼函數(shù)。因?yàn)閐elete_event表示用戶需要關(guān)閉應(yīng)用軟件。對(duì)于delete_event信號(hào)增加回呼函數(shù)包括兩個(gè)步驟。
delete_event的回呼函數(shù)應(yīng)該返回布爾值,用以表示是否允許關(guān)閉窗口。返回TRUR值保持窗口打開(kāi),返回FALSE值表示窗口可以關(guān)閉。如果關(guān)閉窗口,接著發(fā)出destroy信號(hào)告訴應(yīng)用程序就要關(guān)閉窗口。
2.信號(hào)連接和處理函數(shù)
2.1 信號(hào)連接函數(shù) g_signal_connect
??每個(gè)信號(hào)和每個(gè)對(duì)象可以有多個(gè)回調(diào)函數(shù),并且它們會(huì)按設(shè)置的順序依次運(yùn)行。
/* 信號(hào)連接函數(shù)*/ #define g_signal_connect(instance, detailed_signal, c_handler, data) 形參:instance --void*指針,要發(fā)出信號(hào)的構(gòu)件 detailed_signal -- char *指針,連接的信號(hào)的名稱 c_handler --信號(hào)被捕獲時(shí)所要調(diào)用的函數(shù) data -- void*指針,傳遞給信號(hào)處理函數(shù)(回調(diào)函數(shù))的數(shù)據(jù) 返回值:gulong類型,返回識(shí)別回調(diào)函數(shù)的標(biāo)識(shí) 第三個(gè)參數(shù)即回調(diào)函數(shù)一般形式如下: void callback_func( GtkWidget *widget,gpointer callback_data ); 形參:widget -- 指向發(fā)出信號(hào)的構(gòu)件的指針 callback_data --g_signal_connect傳入的參數(shù) 注意:上面回調(diào)函數(shù)的聲明只是一般的形式, 有些構(gòu)件的特殊信號(hào)會(huì)用不同的調(diào)用參數(shù)。
2.2 g_signal_connect返回值
信號(hào)連接函數(shù)g_signal_connect返回值為glong類型,返回一個(gè)識(shí)別回調(diào)函數(shù)的標(biāo)志。因?yàn)槊總€(gè)信號(hào)和每個(gè)對(duì)象可以有多個(gè)回調(diào)函數(shù),并且它們會(huì)按設(shè)置的順序依次運(yùn)行。所以可以通過(guò)這個(gè)返回標(biāo)志,可通過(guò)下面函數(shù)將實(shí)現(xiàn)的回調(diào)函數(shù)刪除:
g_signal_handler_disconnect(gpointer instance, gulong handler_id)
?所以,通過(guò)傳遞你想在上面刪除處理函數(shù)的構(gòu)件,以及某個(gè)signal_connect函數(shù)返回的標(biāo)識(shí),你就可以中斷一個(gè)信號(hào)處理函數(shù)的連接。
也可以使用g_signal_handler_block() 和 g_signal_handler_unblock() 這類函數(shù)來(lái)暫時(shí)斷開(kāi)信號(hào)處理函數(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 信號(hào)連接函數(shù) g_signal_connect_swapped
/*信號(hào)連接函數(shù)*/ #define g_signal_connect_swapped(instance, detailed_signal, c_handler, data) g_signal_connect_swapped()和g_signal_connect() 相同,只是回調(diào)函數(shù)只用一個(gè)參數(shù),一個(gè)指向GTK對(duì)象的指針。所以當(dāng)使用這個(gè)函數(shù)連接信號(hào)時(shí),回調(diào)函數(shù)應(yīng)該是這樣的形式: void callback_func( GtkObject *object );
??擁有兩個(gè)函數(shù)來(lái)設(shè)置信號(hào)連接的目的只是為了允許回調(diào)函數(shù)有不同數(shù)目的參數(shù)。GTK 庫(kù)中許多函數(shù)僅接受一個(gè)單獨(dú)的構(gòu)件指針作為其參數(shù),所以對(duì)于這些函數(shù)你要用 g_signal_connect_swapped(),然而對(duì)你自己定義的函數(shù),你可能需要附加的數(shù)據(jù)提供給你的回調(diào)函數(shù)。
3 事件
??除有信號(hào)機(jī)制外,還有一套 events 反映 X 事件機(jī)制。回調(diào)函數(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
??所以, 連接一個(gè)回調(diào)函數(shù)到這些事件之一,我們會(huì)這樣用:
g_signal_connect (G_OBJECT (button), "button_press_event",G_CALLBACK (button_press_callback), NULL);
??這里假定button是一個(gè)按鈕構(gòu)件。現(xiàn)在,當(dāng)鼠標(biāo)位于按鈕上并按一下鼠標(biāo)時(shí),函數(shù) button_press_callback() 會(huì)被調(diào)用。這個(gè)函數(shù)應(yīng)該聲明為:
static gint button_press_callback( GtkWidget *widget, GdkEventButton *event, gpointer data );
?注意,我們可以把第二個(gè)參數(shù)類型聲明為 GdkEventButton,因?yàn)槲覀冎滥膫€(gè)類型的事件會(huì)發(fā)生。
這個(gè)函數(shù)的返回值指示這個(gè)事件是否應(yīng)該由 GTK 事件處理機(jī)制做進(jìn)一步的傳播。 返回 TRUE 指示這個(gè)事件已經(jīng)處理了,且不應(yīng)該做進(jìn)一步傳播。 返回 FALSE 繼續(xù)正常的事件處理。
3.1 按鍵連接信號(hào)關(guān)閉窗口示例
#include void hello(GtkWidget *widget,gpointer data) { g_print("按鍵信號(hào)觸發(fā)成功n"); } /*事件處理回調(diào)函數(shù)*/ gint delete_event(GtkWidget *widget,GdkEvent *evnet,gpointer data) { g_print("事件處理回調(diào)函數(shù)調(diào)用成功n"); return TRUE;//TRUE表示繼續(xù),F(xiàn)ALSE表示關(guān)閉 } 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è)置窗口標(biāo)題*/ /*信號(hào)連接函數(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); /*設(shè)置容器對(duì)象屬性:設(shè)置窗口邊框?qū)挾葹?00*/ gtk_container_set_border_width(GTK_CONTAINER(window),100); /*創(chuàng)建新的按鈕,設(shè)置按鈕信息為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; }

程序運(yùn)行效果:
當(dāng)我們用鼠標(biāo)按下hello按鈕,按鍵發(fā)出clicked信號(hào),觸發(fā)hello回調(diào)函數(shù),接著調(diào)用下一個(gè)信號(hào)處理函數(shù)gtk_widget_destroy(),將窗口構(gòu)件參數(shù)傳遞給該函數(shù),銷毀窗口,從而窗口發(fā)出destroy信號(hào),然后調(diào)用我們實(shí)現(xiàn)號(hào)的回調(diào)函數(shù)destroy(),實(shí)現(xiàn)程序退出。
審核編輯:湯梓紅
-
信號(hào)
+關(guān)注
關(guān)注
11文章
2854瀏覽量
78364 -
回調(diào)函數(shù)
+關(guān)注
關(guān)注
0文章
89瀏覽量
11912
發(fā)布評(píng)論請(qǐng)先 登錄
一文詳解C語(yǔ)言函數(shù)指針與回調(diào)函數(shù)
C語(yǔ)言里面的函數(shù)指針和回調(diào)函數(shù)
C語(yǔ)言回調(diào)函數(shù)學(xué)習(xí)
LabWindows/CVI 程序 回調(diào)函數(shù)設(shè)計(jì)

回調(diào)函數(shù)的詳細(xì)資料說(shuō)明

C語(yǔ)言函數(shù)的回調(diào)函數(shù)
STM32編程時(shí),如何確定中斷回調(diào)函數(shù)的入口

詳解回調(diào)函數(shù)的概念及使用步驟
一文詳解C/C++回調(diào)函數(shù)
函數(shù)指針和回調(diào)函數(shù)的使用方法
C語(yǔ)言|回調(diào)函數(shù)的不同用法
應(yīng)用筆記 | 淺談STM32庫(kù)里的回調(diào)函數(shù)

評(píng)論