It計算機課件 gtk學習筆記_第1頁
It計算機課件 gtk學習筆記_第2頁
It計算機課件 gtk學習筆記_第3頁
It計算機課件 gtk學習筆記_第4頁
It計算機課件 gtk學習筆記_第5頁
已閱讀5頁,還剩175頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第一章入門

1.1Hello!World!

1.11第一個GTK程序

1.12GTK的對象導向架構(gòu)

1.2Signal與Callback

1.21使用Signal關(guān)閉窗口

1.22自訂callback函式

1.23內(nèi)建Signal的發(fā)射與停止

1.3事件處理

1.31GDK事件結(jié)構(gòu)

1.32GTK事件處理函式

L33事件屏蔽(EventMask)

L4基本版面配置

1.41GtkHBox與GtkVBox

1.42GtkFrame與GtkButtonBox

1.43GtkTable

第二章基本圖形組件

2.1按鈕

2.1IGtkButton與GtkToggleButton

2.12影像及文字按鈕

2.13GtkCheckButton與GtkRadioButton

2.2對話框

2.21GtkMessageDialog

2.22GtkAboutDialog

2.23GtkColorButton與GtkColorSelectionDialog

2.24GtkFontButton與GtkFontSelectionDialog

2.25GtkFileChooserButton與GtkFileChooserDialog

2.26使用GtkDialog自訂對話框

2.3文字字段

2.31GtkEntry

2.32GtkSpinButton

2.33GtkTextView

2.4選項清單

2.HGtkComboBox

2.42GtkComboBox與GtkListStore

2.43GtkComboBox與GtkTreeStore

2.44GtkTreeView與GtkListStore

2.45GtkTreeView,-jGtkTreeStrore

2.5版面組件

2.51GtkNotebook

2.52GtkPaned

2.53GtkScrolledWindow

2.54GtkAlignment>GtkFixed與GtkLayout

2.55GtkFrame與GtkAspectFrame

第三章進階組件使用

3.1選單元件

3.HGtkHandleBox

3.12GtkMenuBar>GtkMenu與GtkMenuItem

3.13GtkCheckMenuItem>GtkRadioMenuitem與GtkTearoffMenuItem

3.14GtkUIManager

3.2列組件

3.2IGtkProgressBar

3.22GtkToolBar

3.23GtkStatusBar

3.3其它組件

3.31GtkStyle與資源檔

3.32GtkLabel

3.33GtkScale

3.34GtkEntryCompletion

3.35GtkArrow

3.36GtkRuler

3.37GtkAssistant

3.38GtkCalendar

3.39GtkDrawingArea

第四章GLib

4.1基本型態(tài)、宏、公用(Utility)函式

4.HGLib基本型態(tài)與宏

4.12GTimer

4.13Timeout與Idle

4.14環(huán)境信息

4.15日志(Logging)

4.2輸入輸出

4.21基本檔案讀寫

4.22目錄信息

4.23GI0Channel與檔案處理

4.24GI0Channel與Pipe

4.3數(shù)據(jù)結(jié)構(gòu)、內(nèi)存配置

4.31GString

4.32GArray、GPtrArray>GByteArray

4.33GSListsGList

4.34GHashTable

4.35GTree與GNode

4.36內(nèi)存配置

4.4執(zhí)行緒

4.41GThread

4.42GMutex

4.43GCond

第一章入門

1.1HellolWorld!

1.11第一個GTK程序

不可免俗的,從最簡單的基本窗口產(chǎn)生開始介紹,窗口標題就叫作「哈啰!GTK+!]好了,

請使用任一編輯器來編輯一個helloGtk.c的檔案,內(nèi)容如下:

helloGtk.c

#include<gtk/gtk.h>

intmain(intargc,char*argv[]){

GtkWidget"window;

gtk_init(&argc,&argv);

window=gtk_window_new(GTK_WINDOW_TOPLEVEL);

gtk_window_set_title(GTK_WINDOW(window),”哈啰!GTK+!");

gtk_widget_show(window);

gtk_main();

return0;

)

首先include必要的GTK標頭檔案,接著先看到gtk_init(),這個函式會先初始化函式庫,

設(shè)定預設(shè)信號處理,并讓GTK有機會處理傳遞給程序的命令列自變量,GTK會檢查是否有以

下的自變量并處理:

-gtk-module

-g-fatal-warnings

-gtk-debug

-gtk-no-debug

-gdk-debug

-gdk-no-debug

-display

-sync

-name

-class

這些自變量會從自變量列中移除,剩下的部份留待您自己的程序邏輯來處理。

GTK雖然使用C來撰寫,但是透過GObject函式庫,可以支持對象導向的對象封裝、繼承觀

念,透過宏還可以支持多型的觀念(至少概念上達到一些部份),一個GTK對象階層如下所

示:

GObject

+--GInitiallyUnowned

+—GtkObject

+--GtkWidget

+-GtkContainer

+--GtkBin

+—GtkWindow

gtk_window_new()會建立一個GtkWindow,這是一個基本的窗口對象,GtkWindow繼承自

GtkBin,GtkBin繼承自GtkContainer,GtkContainer可以容納其它widget,所以在

GtkWindow中可以置放其它的widget,而它們?nèi)际荊tkWidget的后代。

在函式庫的組織上,GTK+的參考手冊中,若要查詢與GtkWindow設(shè)定的相關(guān)函式,也就是

gtk_window開頭的函式名稱,則直接查詢GtkWindow的說明文件。

在范例中,您使用gtk_window_new()在內(nèi)存中產(chǎn)生一個GtkWindow(但還不是真正出現(xiàn)在屏

幕畫面中),參數(shù)設(shè)定為GtkWindowType,有兩個可用的設(shè)定:

GTK_WINDOW_TOPLEVEL:一個有外框的標準GTK窗口。

GTK_WINDOW_POPUP:一個蹦現(xiàn)窗口,像是對話框、蹦現(xiàn)選單或提示文字。

若要設(shè)定GtkWindow標題文字,則使用gtk_window_set_title(),GTKWINDOW宏用以將

window對象轉(zhuǎn)型為GtkWindow型態(tài)。

gtk_window_new()只是在內(nèi)存中產(chǎn)生一個GtkWindow,若要真正在屏幕畫面中顯示GTK的

widget,則使用gtk_widget_show(),最后呼叫g(shù)tk_main(),這會將程序的控制權(quán)交給GTK,

由GTK來等待鍵盤、按鈕等事件或是檔案10通知。

您可以使用以下的指令來進行編譯與執(zhí)行:

$gcchelloGtk.c-ohelloGtk'pkg-config—cflags-libsgtk+?2.0、

$,/helloGtk.

pkg-config會先取得GTK的標頭文件位置與函式庫信息,然后再供給gcc進行編譯,一個

程序的執(zhí)行畫面如下所示,這個程序的原始碼使用UTF8編碼,在編譯執(zhí)行之后,可直接顯

示中文:

由于gtk_main()會將控制權(quán)交給了GTK,直到呼叫g(shù)tk_main_quit()之前都不會返回,這個

范例目前還沒有實作這個部份(之后還會介紹如何實作),因此這個窗口您按下右上X鈕也

不會真正關(guān)閉,而必須在文字模式下先使用CtrlK強制中斷程序。

有關(guān)gtk_main()、gtk_main_quit()等函式的說明,可以參考GTK+參考文件中的Mainloop

andEventSo

1.12GTK的對象導向架構(gòu)

GTK基本上是使用C語言來撰寫,即使C語言本身不支持對象導向,但GTK在架構(gòu)上運用

了一些方式,使得使用GTK時可以支持許多對象導向的概念。

在對象導向的封裝特性上,GTK以結(jié)構(gòu)(structure)的方式來模擬類別,事實上GTK也直

接稱這些結(jié)構(gòu)為類別,以建構(gòu)GtkWindow的程序代碼為例:

window=gtk_window_new(GTK_WINDOW_TOPLEVEL);

在函式的組織上,與GtkWindow相關(guān)的函式,都是以gtk_window名稱作為開頭,

gtk_window_new()就像是對象導向程序語言中的建構(gòu)式,如果要設(shè)置GtkWindow的相關(guān)屬

性,例如標題名稱:

gtk_window_set_ti11e(GTK_WINDOW(window),〃哈啰!GTK+!〃);

gtk_window_set_title()的第一個參數(shù)接受GtkWindow指標,透過這種方式,讓實際上屬于

全域的函式,看來就像是專屬于GtkWindow所使用,就如同對象上所帶有的公開(public)

方法(method)或成員函式(memberfunction),而在私有(private)的模擬上,GTK使

用static函式,例如在gtkwindow.c原始程序代碼中,可以看到:

staticvoidgtk_window_dispose(GObject"object)

staticvoidgtk_window_destroy(GtkObject"object)

staticvoidgtk_window_finalize(GObject"object)

staticvoidgtk_window_show(GtkWidget*widget)

staticvoidgtk_window_hide(GtkWidget*widget)

staticvoidgtk_window_map(GtkWidget*widget)

staticvoidgtk_window_unmap(GtkWidget*widget)

staticvoidgtk_window_realize(GtkWidget*widget)

staticvoidgtk_window_unrealize(GtkWidget*widget)

這些static函式不會出現(xiàn)在gtkwindow.h標頭文件中,僅可在gtkwindow.c中使用,這看

起來就像是GtkWindow的專屬私用函式。

在繼承上,GTK實際上使用結(jié)構(gòu)鏈接(link)的方式,在第一個GTK程序中看過以下的

繼承關(guān)系:

GObject

+-GInitiallyUnowned

+--GtkObject

+―GtkWidget

+一-GtkContainer

+—GtkBin

+--GtkWindow

以GtkContainer為例,在gtkcontainer.h中有如下的定義:

typedefstruct_GtkContainerGtkContainer;

struct_GtkContainer

(

GtkWidgetwidget;

GtkWidget*focus_child;

guintborder_width:16;

/*<private>*/

guintneedresize:1;

guintresize_mode:2;

guintreallocate_redraws:1;

guinthas_focus_chain:1;

};

GtkContainer的成員中有一個GtkWidget,而再來看到gtkwidget.h:

typedefstruct_GtkWindowGtkWindow;

struct_GtkWidget

/*Theobjectstructureneedstobethefirst

*elementinthewidgetstructureinorderfor

*theobjectmechanismtoworkcorrectly.This

*allowsaGtkWidgetpointertobecasttoa

*GtkObjectpointer.

*/

GtkObjectobject;

);

GtkWidget中有個成員為GtkObject,以如此的鏈接關(guān)系來維持對象上的繼承關(guān)系架構(gòu),而

在gtk_window_set_title()函式的使用例子中:

gtkwindow_set_ti11e(GTK_WINDOW(window),”哈啰!GTK+!”);

GTK_WINDOW是一個宏,用來進行指針型態(tài)轉(zhuǎn)型動作:

#defineGTK_WINDOW(obj)

(G_TYPE_C11ECK_INSTANCE_CAST((obj),GTK_TYPE_WINDOW,GtkWindow))

G_TYPE_CIIECK_INSTANCE_CAST宏定義在GLib的gtype.h

(/usr/include/glib-2.O/gobject/gtype.h)中:

#defineG_TYPE_CHECK_INSTANCE_CAST(instance,g_type,c_type)

(_G_TYPE_CIC((instance),(g_type),c_type))

G_TYPE_CHECK_INSTANCE_CAST宏會檢查instance是否為g_type的一個實例,如果不是的

話就發(fā)出警示訊息,若是的話就將指針轉(zhuǎn)型為c_type型態(tài)(參考

G_TYPE_CI1ECK_INSTANCE_CAST在線文件說明)。

即便在熟悉C++、Java等支持對象導向程序語言的人來說,這樣的架構(gòu)在對象導向的概念上

并不完整,但確實在易讀與維護性上加強了不少。

1.2Signal與Callback

1.21使用Signal關(guān)閉窗口

在第一個GTK程序中,當您按下窗口右上X鈕時,在GTK窗口的預設(shè)處理中,只會隱藏

窗口,而不會直接關(guān)閉程序,GTK有一套Signal與Callback函式的處理機制,在某個動作

發(fā)生時,GTK會發(fā)出特定Signal,若您想要進行某些處理,則需定義Callback函式,并透

過g_signal_connect()等函式,將Signal與Callback函式加以連結(jié)。

以按下窗口右上X鈕為例,按下X鈕后,GTK預設(shè)會發(fā)出"destroy”的Signal,您可以使用

g_signal_connect()將之連結(jié)至gtk_main_quit()函式,這個函式會結(jié)束gtk_main()的循環(huán)

處理因而結(jié)束GTK程序:

#include<gtk/gtk.h>

intmain(intargc,char*argv[]){

GtkWidget"window;

gtk_init(&argc,&argv);

window=gtk_window_new(GTK_WINDOW_TOPLEVEL);

glk_window_set_title(GTK_WINDOW(window),”哈啰!GTK+!”);

g_signal_connect(GTK_OBJECT(window),"destroy",

G_CALLBACK(gtk_main_quit),NULL);

gtk_widget_show(window);

gtk_main();

return0;

)

從g_、G_開頭的函式名稱可以知道,它們是GLib所提供的函式與宏(在GTK+2.0中,Signal

處理已由GTK移至GLib),g_signal_connect()第一個參數(shù),必須是GtkObject或其衍生的

類別實例,代表Signal發(fā)出的來源對象,第二個參數(shù)是感興趣的信號,第三個參數(shù)是

Callback函式,G_CALLBACK宏強制會轉(zhuǎn)換函式型態(tài)為無參數(shù)無傳回值的GCallback函式型

態(tài):

#defineG_CALLBACK(f)((GCallback)(f))

在這邊使用GTK的gtkjnain_quit()函式,第四個參數(shù)是可以傳遞給CalIback函式的相關(guān)

資料,在這邊不需要,設(shè)定為NULL即可。

g_signal_connect()實際上是宏(定義在/usr/include/glib-2.O/gobject/gsignaLh),方

便使用g_signal_connect_data()函式:

#defineg_signal_connect(instance,detailed_signal,c_handler,data)\

g_signal_connect_data((instance),(detailed_signal),(c_handler),(data),

NULL,(GConnectFlags)0)

g_signal_connect_data()會傳回gulong型態(tài)的handlerid,函式的定義如下:

gulongg_signal_connect_data(gpointerinstance,

constgchar*detailed_signal,

GCallbackc_handler,

gpointerdata,

GClosureNotifydestroy_data,

GConnectFlagsconnect_flags);

如果您打算將Signal與Callback斷開連結(jié),可以根據(jù)傳回的handlerid來使用

g_signal_handler_disconnect()函式,也可以根據(jù)handlerid來使用

g_signal_handler_is_connected()函式,測試Signal的連接狀態(tài):

voidg_signal_handler_disconnect(gpointerobject,gulongid);

gbooleang_signal_handler_is_connected(gpointerinstance,gulonghandler_id);

例如一個連接Signal與斷開Signal的程序片段如下:

gulonghandler_id=g_signal_connect(GTK_OBJECT(window),“destroy”,

G_CALLBACK(gtk_main_quit),NULL);

if(g_signal_handler_is_connected(window,id)){

g_signal_hand1er_disconnect(GTK_OBJECTS(window),handler_id);

}

若只是想暫停(block)某Signal處理,則可以使用g_signal_handler_block(),想恢復

被暫停的Signal處理,則可以使用g_signal_handler_unblock():

voidg_signal_handler_block(gpointerobject,gulongid);

voidg_signal_handler_unblock(gpointerobject,gulongid);

一個被g_signal_handler_block()函式呼叫n次的Signal處理,也必須被

g_signal_handler_unblock()相對應(yīng)的次數(shù),才可以恢復原本來未暫停的狀態(tài)。

若在未知handlerid的情況下,想要中斷、暫?;蚧謴托盘栠B結(jié),則可以嘗試使用

g_signal_handlers_disconnect_by_func()、g_signal_hand1ers_b1ock_by_func()、

g_signal_handlers_unblock_by_func(),這三者其實都是宏:

ftdefineg_signal_handlers_disconnect_by_func(instance,func,data)\

g_signal_handlers_disconnect_matched((instance),\

(GSignalMatchType)(G_SIGNAL_MATCH_FUNC|G_SIGNAL_MATCH_DATA),\

0,0,NULL,(func),(data))

#defineg_signal_handlers_block_by_func(instance,func,data)\

g_signal_handlers_block_matched((instance),\

(GSignalMatchType)(G_SIGNAL_MATCH_FUNCIG_SIGNAL_MATCH_DATA),\

0,0,NULL,(func),(data))

#defineg_signal_handlers_unb1ock_by_func(instance,func,data)\

g_signal_hand1ers_unb1ockmatched((instance),\

(GSignalMatchType)(G_SIGNAL_MATCH_FUNC|G_SIGNAL_MATCII_DATA),\

0,0,NULL,(func),(data))

g_signal_handlers_disconnect_matched()、g_signal_handlers_b1ock_matched()、

g_signal_handlers_unblock_matched()會傳回guint的數(shù)值,表示符合的handler數(shù)目:

guintg_signal_handlers_disconnect_matched(gpointerinstance,

GSignalMatchTypemask,

guintsignal_id,

GQuarkdetail,

GClosure*closure,

gpointerfunc,

gpointerdata);

guintg_signal_handlers_block_matched(gpointerinstance,

GSigna1MatchTypemask,

guintsignal_id,

GQuarkdetail,

GClosure"closure,

gpointerfunc,

gpointerdata);

guintg_signal_handlers_unblock_matched(gpointerinstance,

GSignalMatchTypemask,

guintsignal_id,

GQuarkdetail,

GClosure"closure,

gpointerfunc,

gpointerdata);

更多有關(guān)Signal函式的說明,可以參考GObject參考文件的Signals。

1.22自訂callback函式

您可以自訂callback函式,使用g_signa_connect()函式連接,在指定的Signal發(fā)生時呼

叫自訂的callback函式,自訂的callback函式原型基本上是以下的形式:

voidfunc_name(GtkWidget*widget,...,gpointeruser_data);

第一個參數(shù)是發(fā)出信號的Widget指針,第二個參數(shù)是呼叫callback函式時,所要傳遞給

callback函式的相關(guān)數(shù)據(jù),舉個實際的例子,下面這個范例會有一個按鈕,當按下按鈕時,

會在主控臺下顯示指定的訊息:

callbackdemo,c

#include<gtk/gtk.h>

//自訂Callback函式

voidbutton_clicked(GtkWidget"button,gpointerdata){

g_print("按鈕按下:%s\n",(char*)data);

)

intmain(intargc,char*argv[]){

GtkWidget"window;

GtkWidget*button;

gtk_init(&argc,&argv);

window=gtk_window_new(GTK_WINDOW_TOPLEVEL);

gtk_window_set_title(GTK_WINDOW(window),”哈啰!GTK+!”);

button=gtk_button_new_with」abel(“按我”);

gtk_container_add(GTK_CONTAINER(window),button);

g_signal_connect(GTK_OBJECT(window),''destroy",

G_CALLBACK(gtk_main_quit),NULL);

g_signal_connect(GTK_OBJECT(button),"clicked'1,

G_CALLBACK(button_clicked),”哈啰!按鈕!)

gtk_widget_show(window);

gtk_widget_show(button);

gtk_main();

return0;

)

這個范例是以使用Signal關(guān)閉窗口為基礎(chǔ),增加了一個按鈕,程序中注意的是Callback

函式的定義,而要產(chǎn)生一個具有文字的按鈕,可以使用gtk_button_new_with_label()函式,

由于GtkWindow是GtkContainer的子類,所以它可以容納其它的Widget組件,在這邊使

用gtk_container_add()函式將GtkButton加入GtkWindow之中,目前沒有設(shè)置任何版面配

置,所以按鈕就填滿整個窗口。

要連接自訂的Callback函式,一樣使用g_signal_connect(),注意到雖然G_CALLBACK宏

會將函式指針轉(zhuǎn)換為無參數(shù)無傳回值的型態(tài),但這不代表Callback函式不可以傳回值或帶

有參數(shù),實際操作時是依當時所連接的函式型態(tài)而定,在這邊,g_signal_connect()最后一

個參數(shù)將傳遞給button_clicked0函式的data參數(shù)。

要顯示加入的GtkButton,在這邊再次使用gtk_widget_show(),您也可以直接使用

gtk_widget_show_all0,將所有在指定的GtkContainer中的組件都顯示出來:

gtk_widget_show_all(window);

一個執(zhí)行時的畫面如下所示:

口caterpillar@caterpillar:-/workspaceIfgIIX

棍案(E)^i(E)示但)終端橫(工)分氟旦)求助出)

-按^

-

按tfl按下:哈>0.

J按翅

J

按鈕按下:哈嘴J

按翅

按tfl按下:哈嘴.二

按黜按下:哈喔.二

按iB

按IS按下:哈嘴.二

按is

按翅按下:哈喋.二

J按

J鈕

按鈕按下:哈嘴J

J按

J鈕

按tfl按下:哈嘴J

按蛆按下:哈喔.二

二is

技黜技下:哈喉.翅

-翅

-

按按下:哈嘴-

tfiJ按

J翅

按按下:哈嘴J

IH按

-翅

-

按翅按下:哈.

11按

-翅

按鈕按下:哈嘴.-

J按

J翅

J

按tfi按下:哈嘴按

按按下:哈嘴.二

.二

按按下:哈嘴按

tflJ

J翅

按蛆按下:哈嘴J

.二

按tfi按下:哈嘴按

-翅

按按下:哈嘴.按

.二

按tfi按下:哈嘴按

按鈕按下:哈嘿.按

-赳

按翅按下:哈嘴.-

另一個較少使用的Signal連結(jié)函式是g_signal_connect_swapped(),它實際上也是個宏,

方便使用g_signalconnect_data()函式,定義如下:

#definegsignalconnectswapped(instance,detailedsignal,chandler,data)\

g_signal_connect_data((instance),(detailed_signal),(c_handler),(data),

NULL,G_CONNECT_SWAPPED)

它所對應(yīng)的Callback函式應(yīng)如下定義:

voidfuncname(gpointeruserdata,...,GtkWidget*widget);

簡單的說,就是兩個參數(shù)對調(diào),g_signal_connect_swapped()常用來接結(jié)僅接受一個單獨

Widget作為參數(shù)的callback函式,舉個例子來說,像gtk_widget_destroy()函式:

voidgtk_widget_destroy(GtkWidget*widget);

這個函式會消除指定的Widget,若您在程序中,想要指定消除一個Widget,則可以使用這

個函式,舉例來說,若要按下按鈕后,消除GtkWindow,則可以如下:

callback_demo.c

#include<gtk/gtk.h>

intmain(intargc,char*argv[]){

GtkWidget"window;

GtkWidget"button;

gtk_init(&argc,&argv);

window=gtk_window_new(GTK_WINDOW_TOPLEVEL);

gtk_window_set_title(GTK_WINDOW(window),”哈啰!GTK+!”);

button=gtk_button_new_with」abel(“按我”);

gtk_container_add(GTK_CONTAINER(window),button);

g_signal_connect(GTK_OBJECT(window),"destroy",

G_CALLBACK(gtk_main_quit),NULL);

g_signal_connect_swapped(GTK_OBJECT(button),"clicked'1,

G_CALLBACK(gtk_widget_destroy),window);

gtk_widget_show_all(window);

gtk_main();

return0;

)

這個程序在按下按鈕后,會消去window所儲存的GtkWindow,由于這是唯一個GtkWindow,

消除后程序也就跟著結(jié)束。您也可以如前一個范例,在自訂的button_clicked()函式中呼

叫g(shù)tk_widget_destroy():

callback_demo.c

#include<gtk/gtk.h>

//自訂Callback函式

voidbutton_clicked(GtkWidget"button,gpointerdata){

gtk_widget_destroy((GtkWidget*)data);

)

intmain(intargc,char*argv[]){

GtkWidget"window;

GtkWidget"button;

gtk_init(&argc,&argv);

window=gtk_window_new(GTK_WINDOW_TOPLEVEL);

gtk_window_set_title(GTK_WINDOW(window),”哈啰!GTK+!0);

button=gtk_button_new_with」abel("按我");

gtk_container_add(GTK_CONTAINER(window),button);

g_signal_connect(GTK_OBJECT(window),"destroy",

G_CALLBACK(gtk_main_quit),NULL);

g_signal_connect(GTK_OBJECT(button),"clicked",

G_CALLBACK(button_clicked),NULL);

gtk_widget_show_all(window);

gtk_main();

return0;

1

雖然程序的執(zhí)行也可以透過按下按鈕消除GtkWindow,但直接使用

g_signal_connect_swapped()會是比較直接的方式。

另也還有個g_signal_connect_after()函式值得注意,它實際也是宏,定義如下:

#defineg_signal_connect_after(instance,detailed_signal,c_handler,data)\

g_signal_connect_data((instance),(detailed_signal),(c_handler),(data),

NULL,G_CONNECT_AFTER)

若您使用g_signal_connect_aftcr()來連接callback函式,則該callback函式,會在所

有使用g_signal_connect()設(shè)定的callback函式執(zhí)行之后再執(zhí)行。

L23內(nèi)建Signal的發(fā)射與停止

GTK的Signal不一定得由事件來發(fā)出,您可以主動發(fā)出Signal,利用

g_signal_emit_by_nanie(),您可以指定一個對象已建立的Signal名稱來發(fā)出該Signalo

下面這個程序利用P0SIX執(zhí)行緒(GLib亦有提供GThread來啟用多執(zhí)行緒),改寫自訂

callback函式中的范例,每秒發(fā)出一個GtkButton的〃clicked"Signal,程序開始后即使

您沒有按下按鈕,也會在終端機下顯示〃按鈕按下:哈啰!按鈕!〃的訊息:

signal_emit_demo.c

#include<gtk/gtk.h>

#include<pthread.h>

void*signal_thread(void*arg){

inti;

for(i=0;i<5;i++){

sleep(l);

g_signal_emit_by_name(arg,"clicked");

)

pthread_exit("Threadexit");

)

//自訂Callback函式

voidbutton_clicked(GtkWidget"button,gpointerdata){

g_print("按鈕按下:%s\n",(char*)data);

)

intmain(intargc,char*argv[]){

pthread_ta_thread;

GtkWidget"window;

GtkWidget"button;

gtk_init(&argc,&argv);

window=gtk_window_new(GTK_WINDOW_TOPLEVEL);

gtk_window_set_title(GTK_WINDOW(window),”哈啰!GTK+!”);

button=gtk_button_new_with_label("按我");

gtk_container_add(GTK_CONTAINER(window),button);

g_signal_connect(GTK_OBJECT(window),"destroy",

G_CALLBACK(gtk_main_quit),NULL);

g_signal_connecl(GTK_OBJECT(butlon),"clicked”,

G_CALLBACK(button_clicked),”哈啰!按鈕!”);

gtk_widget_show(window);

gtk_widget_show(button);

pthread_create(&a_lhread,NULL,signal_thread,button);

gtk_main();

return0;

)

程序執(zhí)行后,會使用另一個執(zhí)行緒,每秒發(fā)出一個“clicked”Signal,為了使用POSIX執(zhí)行緒,

編譯這個程序時需要定義.REENTRANT及使用pthread鏈接庫:

$gccsignal_emit_demo.c-osignal_emit_demo-D_REENTRANT-Ipthread'pkg-config—cflags

-libsgtk+?2.0、

g_signal_emit_by_name()可以發(fā)出Signal,如果您想要中止Signal的傳播,則可以使用

g_signal_stop_by_name(),例如在某個Signal處理函式處理完畢后,若不想讓其它的Signal

處理函式繼續(xù)處理了,則可以使用g_signal_stop_by_name()來停止Signalo

若不想使用pthread來撰寫這個程序,則可以考慮使用GLib的Timeout。

1.3事件處理

1.31GDK事件結(jié)構(gòu)

GTK透過GDK來處理事件,GDK會將每個接受到的XEvent轉(zhuǎn)換為GdkEvent,然后傳播給

GtkWidget,引發(fā)一個與事件相對應(yīng)的事件Signal,再透過Callback函式處理事件。

GdkEvent是個Cunion的定義:

unionGdkEvent

GdkEventTypetype;

GdkEventAnyany;

GdkEventExposeexpose;

GdkEventNoExposeno_expose;

GdkEventVisibilityvisibility;

GdkEventMotionmotion;

GdkEventButtonbutton;

GdkEventScrol1scroll;

GdkEventKeykey;

GdkEventCrossingcrossing;

GdkEventFocusfocus_change;

GdkEventConfigureconfigure;

GdkEventPropertyproperty;

GdkEventSelectionselection;

GdkEventOwnerChangeowner_change;

GdkEventProximityproximity;

GdkEventClientclient;

GdkEventDNDdnd;

GdkEventWindowStatewindow_state;

GdkEventSettingsetting;

GdkEventGrabBrokengrab_broken;

);

GdkEvent代表所有的事件型態(tài),其成員GdkEventType為enum型態(tài),可透過它來了解目前

的事件是哪個類型:

GdkEventTypetype=event->type;//event的宣告為GdkEvent*event

switch(type){

caseGDKDELETE:

g_print(z,GDK_DELETE,z);

break;

caseGDK_DESTROY:

g_printCGDK_DELETE");

break;

}

一個使用的例子是,您可以設(shè)計一個接受所有事件的處理函式,根據(jù)GdkEventType來決定

對所有事件作過濾處理,方式就如上面的程序代碼片段所示范的,一個GdkEvent可能對應(yīng)

多個GdkEventType,例如GdkButtonEvent可以對應(yīng)的GdkEventType有GDK_BUTTON_PRESS>

GDK_2BUTT0N_PRESS、GDK_3BUTT0N_PRESS與GDK_BUTTON_RELEASEo

每個事件結(jié)構(gòu)有其個別成員,例如GdkEventButton有x與y成員,代表鼠標光標相對于窗

口的位置:

typedefstruct{

GdkEventTypetype;

GdkWindow*window;

gint8send_event;

guint32time;

gdoublex;

gdoubley;

gdouble*axes;

guintstate;

guintbutton;

GdkDevice"device;

gdoublex_root,y_root;

}GdkEventButton;

您可以這么存取x或y成員:

gdoublex=event->button.x;

gdoubley=event->button,y;

或是將之轉(zhuǎn)型為GdkEventButton再進行存取:

gdoublex=((GdkEventButton*)event)->x;

gdoubley=((GdkEventButton*)event)->y;

GdkEvent傳播給GtkWidget,引發(fā)一個與事件相對應(yīng)的事件Signal,您可以使用

g_signal_cormect()函式連結(jié)該Signal與Callback函式來處理事件,事件類型與對應(yīng)的事

件Signal名稱,基本上就是去掉GDK_名稱,轉(zhuǎn)為小寫并加上_event名稱,例如:

GDKDELETEdelete_event

GDK_DESTROYdestroy_event

GDK_EXPOSEexpose_event

GDK_M0TI0N_N0TIFYmotion_notify_event

GDK_BUTTON_PRESSbutton_press_event

GDK_2BUTT0N_PRESSbutton_press_event

GDK_3BUTT0N_PRESSbutton_press_event

GDKBUTTONRELEASEbutton_release_event

GDKKEY_PRESSkey_press_event

GDK_KEY_RELEASEkey_release_event

GDK_ENTER_NOTIFYenter_notify_event

GDK_LEAVE_NOT1FYleave_notify_event

GDK_FOCUS_CHANGEfocus_in_event,focus_out_event

GDK_CONFIGUREconfigure_event

GDK_MAPmap_event

GDKUNMAPunmap_event

GDKPROPERTY_NOTIFYproperty_notify_event

GDK_SELECTION_CLEARselection_clear_event

GDK_SELECTION_REQUESTselection_request_event

GDK_SELECTION_NOTIFYselection_notify_event

GDK_PROXIMITY_INproximity_in_event

GDK_PROXIMITY_OUTproximity_out_event

GDK_CLIENT_EVENTclient_event

GDK_VISIBIL

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論