كار رو با يك مثال ساده شروع مي كنم در اين مثال مطالبي مطرح ميشه كه در بيشتر برنامه ها يي كه بعدا مي نويسيم استفاده مي شه مثال اولكد:#include gtk/gtk.h int main(int argc , char *argv[] ) {GtkWidget *window ;gtk_init( argc , argv);window=gtk_window_new(GTK_WINDOW_TOPLEVEL);g tk_widget_show(window);gtk_main();Return 0;}خط اول : همه برنامه هايي كه از gtk استفاده مي كنند شامل اين خط مي شوند كه اين سرفايل شامل تعريف متغيير ها توابع و ساختار ها و غيره مي شه و بايد در برنامه هاي خود انرا بگنجانيم .خط چهارم : در اين خط ما تابع gtk_init را فراخواني كرديم كه اين خط هم در تمام برنامه ها استفاده مي شه و برخي چيزها رو براي ما تنظيم مي كنه مثل مقدار پايه و رنگ كه نتيجه فراخواني اين تابع است و بطور كلي اين كتابخانه رو بصورت خودكار براي ما مقداردهي اوليه مي كنه.خط پنجم و ششم : در اين خطوط ما يك پنجره براي برنامه خود ايجاد كرديم كه درصورتي كه ما سايز انرا مشخص نكنيم بصورت پيش فرض 200 در 200 در نظر گرفته مي شود زياد نگران نحوه ايجادش و كدهاش نباشيد به زودي همه انها را خواهيد اموخت.خط ششم : مي گويد كه ما widget خود را تنظيم كرديم و ويژگي هاي لازم را تنظيم كرديم و حال مي خواهيم كه انرا براي ما نشان دهد (widget يك شي هست مثلا يك دكمه يا يك تكست باكس)خط هفتم : تابع gtk_main را فراخواني مي كنيم كه ان نيز در تمام برنامه هايي كه از gtk استفاده مي كنيم بايد در كد هاي ما قرار داشته باشه . وقتي برنامه به اين نقطه مي رسد gtk به حالت خواب ميره و منتظر رويداد x مي شه ( مثل كليك موس يا فشار يك دكمه ) در واقع يك حلقه رو ايجاد مي كنه كه مدام اجرا ميشه تا اينكه يك رويداد اتفاق بيفته و در برابر ان عكس العمل انجام بده .انچه كه از اين مثال فهميديمقالب كلي يك برنامه كه از gtk استفاده مي كند در اكثر موارد به شكل زير مي باشدكد:#include gtk/gtk.h int main(int argc, char argv[]){gtk_init( argc, argv);gtk_main();return 0;}براي كامپايل برنامه در لينوكس مي تونيد از دستور زير استفاده كنيدg++ `pkg-config --cflags --libs gtk+-2.0` -o name.cpp nameout كه بجاي name.cpp مسير جايي رو كه در انجا برنامه رو ذخيره كرديد مي ديد و nameout هم نامي هست كه مي خواهيد برنامه كامپايل شده داشته باشه.اگه تو ويندوز كد مي نويسيد مي تونيد دستوراتي كه تو مقاله اي كه تو سايت نوشتم بخونيدمقاله نحوه نصب gtk در ويندوز و پيكربندي ان براي كامپايل برنامه ها با ويژوال سي پلاس پلاساگه همه كار ها رو درست انجام داده باشيد بايد زماني كه برنامه خود را اجرا مي كنيد مثل شكل پايين باشهمثال دوم در مثال قبل شما ساختار كلي يك برنامه رو كه از gtk استفاده مي كرد ديديد در اين مثال من مي خوام نحوه ايجاد يك widget رو به شما اموزش بدمWidget چيه گفتم كه منظور از widget يك شي هست و gtk در واقع كتابخانه اي كه شامل يك سري widget ها مثل label يا button و ... هست كه ما از اونها استفاده مي كنيم براي ايجاد يك رابط گرافيكي و اما مثالكد:#include gtk/gtk.h int main(int argc , char *argv[]){gtk_init( argc, argv);GtkWidget *window;GtkWidget *button;window=gtk_window_new(GTK_WINDOW_TOPLEVEL) ;button=gtk_button_new();gtk_container_add(GTK_CON TAINER(window),button);gtk_widget_show(window);gtk _widget_show(button);gtk_main();return 0;}با اجراي اين برنامه شما يك پنجره و دكمه كه در اون وجود داره رو مي بينيد حال توضيح كد بالا : برخي از قسمت ها بايد براي شما اشنا باشه چون اونها رو در مثال اول هم بكار برديم و گفتيم كه توابعي مثل gtk_init و gtk_main توابعي هستن كه در تمام برنامه ها بايد وجود داشته باشند حال توضيح قسمت هاي ديگر كدما براي ايجاد هر يكwidget ( در مثال بالا يك دكمه ) سه خط كد بايد به برنامه خود اضافه كنيم ان سه خط اينها هستنكد:GtkWidget * name ;name=gtk_namebase_new();gtk_widget_show(name);ا ن سه خط رو ما در اكثر موارد براي ايجاد widget دلخواه خود به كد هامون اضافه مي كنيمدر خط اول ما يك اشاره گر از نوع gtk تعريف مي كنيم كه name در واقع نام اون اشاره گر هست در خط دوم ما براي اشاره گر خود تخصيص حافظه مي كنيم و با استفاده از تابعي كه در بالا اشاره شد اون widget كه مي خواهيم مي سازيم در خط بعدش هم مي گيم اون widget كه ساختيم به ما نشون بده همين!! در كد بالا namebase اون نوع widget هست كه مي خواهيم بسازيم البته در مورد تابع gtk_namebase_new() بايد گفت كه اين تابع يك الگوي عام هست و براي برخي widget ها كمي شكلش فرق مي كنه كه براي اطلاعات بيشتر مي تونيد به راهنماي كتابخانه مراجعه كنيد يا اينكه صبر كنيد تا من در پست هاي بعدي بگم خوب براي دست گرمي ما براي ايجاد يك label از كدهاي زير استفاده مي كنيمكد:GtkWidget * Label1 ;Label1=gtk_label_new();gtk_widget_show(Label1);ب ر طبق مطالبي كه در بالا ذكر كردم ما در مثال دوم 2 widget ساختيم يكي پنجره و يك دكمه كه كدهاشون اين بودكد:GtkWidget *button;button=gtk_button_new();gtk_widget_show(bu tton);اگه بخوايم بر روي دكمه اي كه ايجاد مي كنيم مطلبي نوشته باشد مي تونيم از تابع gtk_button_new_with_label(“string”) استفاده كنيم كه بر اين اساس كد هاي بالا بدين شكل ميشهكد:GtkWidget *button;button=gtk_button_new_with_label(“Welcom e”);gtk_widget_show(button);كه يك دكمه ايجاد ميكنه كه روي ان عبارت Welcome نوشته شده . نگران اين توابع نباشيد من تك تك اين widget ها رو با ويژگي ها و توابع انها بيان خواهم كرد من فقط مي خوام شما شكل كلي كدها رو ياد بگيريد اينطوري كار راحت تر ميشه .خوب widget ديگر ما يك پنجره بود كد:GtkWidget *window;window=gtk_window_new(GTK_WINDOW_TOPLEVEL) ;gtk_widget_show(window);كه كد هاي بالا براي ايجاد اون بود در مورد پارامتر تابع gtk_window_new() بايد بگم كه تنها دو مقدار براش وجود داره عبارت GTK_WINDOW_TOPLEVEL براي ايجاد يك پنجره ساده و عبارت GTK_WINDOW_POPUP براي ايجاد يك پنجره پاپاپ .خوب از توابع ديگه اي كه براي تنظيم پنجره بكار ميره مي شه به توابع زير اشاره كردكد:gtk_window_set_title(GTK_WINDOW(name), string”);كه براي تنظيم عنوان پنجره استفاده مي شه و name نام اشاره گري هست كه به پنجره اشاره مي كنه و string هم عنوان پنجره ميشه مثلا براي مثال دو ميشه اين كد:gtk_window_set_title(GTK_WINDOW(window),”We lcome”);و با استفاده از تابع زير هم مي تونيد خاصيت resize پنجره رو فعال يا غير فعال كنيدكد:gtk_window_set_resizable(GTK_WINDOW(n ame),Boolean);كه مثلا اگه بخوايم در پنجره مثال دوم ما خاصيت resize غير فعال بشه كد ما ميشه اينكد:gtk_window_set_resizable(GTK_WINDOW(win dow),FALSE);براي تعيين اندازه پنجره هم مي تونيد از تابع زير استفاده كنيد كد:gtk_widget_set_size_request(GTK_WIDGET(name), width,hight);خوب برگرديم به مثال دوم در اونجا يه خط كد هست كه هنوز توضيح ندادم كد:gtk_container_add(GTK_CONTAINER(window),butto n);خوب با استفاده از اين تابع به gtk مي گيم كه دكمه ما رو در درون پنجره قرار بده . اين تابع تنها مي تونه يك widget رو در پنجره قرار بده و اگه شما دوتا دكمه داشته باشيد اين تابع ديگه جواب گو نيست و بايد از روشي به نام بسته بندي كردن widget استفاده كنيم كه در پست بعدي به بيان اون مي پردازم .وقتي كه ما يك برنامه كاربردي ايجاد مي كنيم عمدتا بيش از يك widget رو در پنجره خود قرار مي ديم .ما در مثال دوم يك دكمه رو در پنجره خود قرار داديم كه اين كار رو با استفاده از تابع gtk_container_add() انجام داديم كه كار اين تابع اين هست كه يك widget رو براي ما در پنجره قرار بده ولي حال اگه بخوايم بيش از يك widget رو در پنجره قرار بديم بايد چكار كنيم ؟ براي اين كار ما از روش بسته بندي widget ها استفاده مي كنيم . بسته بندي widget ها رو به دو طريق ميشه انجام داد استفاده از جدول يا استفاده از جعبه .كه در اين پست روش بسته بندي با استفاده از جدول رو اموزش مي دم و روش بسته بندي با استفاده از جعبه ها رو در پست اينده اموزش مي دم .بسته بندي با استفاده از جدول ها براي استفاده از اين روش ابتدا ما يك جدول ايجاد مي كنيم بعد هر يك از widget ها رو در خانه هاي اون قرار مي ديم . براي رسم يك جدول از تابع زير استفاده مي كنيم كد:gtk_table_new(rows , columns , Boolean);كه پارامتر اول تعداد سطر هاي جدول پارامتر دوم تعداد ستون هاي جدول و پارامتر سوم اگر TRUE باشه جدول خاصيت resize پيدا مي كنه و اندازه خونه هاي جدول برابر با اندازه بزرگترين widget مي شه و اگر FALSE باشه ديگه اين امكان وجود نخواهد داشت .نكته اي كه اينجا وجود داره نحوه شماره گذاري سطر ها و ستون ها در جدول هست كه از صفر شروع مي شه مثلا براي يك جدول 2 در 2 شماره سطر و ستون ها بدين شكل خواهد بود .خوب هون طور كه گفته بودم براي ايجاد هر widget به سه خط كد احتياج داريم الان براي ايجاد يك جدول كدها مون مي شه اين كد:GtkWidget *table1;table1=gtk_table_new(2 ,2 ,FALSE) ;gtk_widget_show(table1);خوب حالا براي اينكه widget هاي خودمون رو در خانه هاي جدول قرار بديم از تابع زير استفاده مي كنيمكد:gtk_table_attach_defaults(GTK_TABLE(n ame) , widget name , left_attach , right_attach , top_attach , bottom_attach ) ;كه به جاي name نام جدول به جاي widget name هم نام اون widget كه مي خوام در جدول قرار بديم و پارامتر هاي ديگه اون هم مشخصات اون سلولي از جدول هست كه مي خوايم widgt رو توش قرار بديم استفاده از جدول براي قرار دادن widget ها كمي مشكل هست نه از جهت كد بلكه تنظيم مكان قرار گرفتن widget ها در خانه هاي ان به همين علت من زياد به اون نمي پردازم فكر كنم در همين حد هم كافي باشه اين هم يك مثال از كاربرد اونكد:#include gtk/gtk.h int main(int argc , char *argv[]){gtk_init( argc, argv);GtkWidget *window ;GtkWidget *table ;GtkWidget *button1;GtkWidget *button2;window= gtk_window_new(GTK_WINDOW_TOPLEVEL);table=gtk_tabl e_new(1,2,FALSE);gtk_container_add(GTK_CONTAINER(w indow),table);button1=gtk_button_new_with_label( BUTTON 1”);button2=gtk_button_new_with_label(“BUTTON 2”);gtk_table_attach_defaults(GTK_TABLE(table),b utton1,0,1,0,1); gtk_table_attach_defaults(GTK_TABLE(table),button2 ,1,2,0,1);gtk_widget_show(window);gtk_widget_show( table);gtk_widget_show(button1);gtk_widget_show(bu tton2);gtk_main();return 0;}توجه كنيد كه شما اول بايد با استفاده از تابع gtk_container_add جدول را در پنجره قرار دهيد سپس هر يك از دكمه ها را در جدول در ضمن بجاي اين چهار خط كد كد:gtk_widget_show(window);gtk_widget_show(table );gtk_widget_show(button1);gtk_widget_show(button2 );مي تونيد از تابع زير استفاده كنيد كه همون كار رو انجام ميدهكد:gtk_widget_show_all(window);روش دوم بسته بندي widget ها با استفاده از جعبه ها :اين روش پركاربردترين روش بسته بندي هست كه به دو شكل افقي يا عمودي صورت مي گيره كه براي قرار دادن اونها از چپ به راست يا برعكسش از جعبه افقي كه با تابع gtk_hbox_new() ايجاد ميشه و براي قرار دادن اونها در پنجره از بالا به پايين يا برعكسش از جعبه عمودي كه با تابع gtk_vbox_new() ايجاد ميشه انجام ميشه . و براي قرار دادن widget ها در جعبه ها هم از توابع gtk_box_pack_start() براي قرار دادن widget ها از چپ به راست در جعبه افقي و از بالا به پايين در جعبه عمودي يا gtk_box_pack_end() براي قرار دادن widget ها از راست به چپ در جعبه افقي و از پايين به بالا در جعبه عمودي استفاده مي كنيم . كار با جعبه ها كمي پيچيده هست و اپشن هاي فراواني داره كه من سعي مي كنم تا اونجايي كه خودم فهميدم و بلدم اينجا بنويسم .خوب براي ايجاد جعبه افقي از تابع زير استفاده مي كنيم كد:gtk_hbox_new(Boolean , int) ;كه ارگومان اول بررسي مي كنه كه ايا سايز هر شي كه در اون قرار مي گيره يكسان باشه يا نه منظور از سايز در جعبه افقي پهناي هر widget مي باشد و ارگومان بعدي ميزان فاصله بين دو شي هست كه در اون قرار مي گيره .همون طور كه گفتم براي ايجاد هر شي نياز به سه خط كد هست پس شكل كامل كدش ميشه اينكد:GtkWidget *hbox ;hbox=gtk_hbox_new(TRUE , 5);gtk_widget_show(hbox);خوب براي ايجاد يك جعبه عمودي هم از تابع زير استفاده مي كنيم كد:gtk_vbox_new(Boolean , int );كه ارگومان اول بررسي مي كنه كه ايا whdget هايي كه در اون قرار مي گيرند ارتفاع يكساني داشته باشند يا خير و ارگومان بعدي هم فاصله بين دو widget رو تنظيم مي كنه .خوب به توابعي مي پردازيم كه براي قرار دادن اشيا در جعبه ها استفاده مي شن من فقط تابع gtk_box_pach_start رو مي گم چون رايج تر هست خوب اين تابع هم بشكل زير هستكد:gtk_box_pack_start (GTK_BOX(name) , widget name , Boolean expand , Boolean fill , int padding ) ;ارگومان اول نام جعبه ما ارگومان دوم نام عنصري كه مي خوايم تو جعبه بزاريم ارگومان سوم مي گه كه ايا اون عناصر تمام فضاي اضافي جعبه رو پر كنن يا نه فضاي خالي وجود داشته باشه ( توضيحات بيشتر در مثال ها ) ارگومان چهارم مي گه كه فضاي اضافي به سايز اشيا اختصاص داده بشه (TRUE ) يا به جعبه اختصاص داده شه و در اطراف هر شي پراكنده شود ( FALSE ) اين گزينه زماني كار مي كنه كه ارگومان سوم به TRUE ست بشه و ارگومان اخر هم يه مقدار فضاي خالي در اطراف هر شي ايجاد مي كنه . اوه تموم شد!!!!اگه چيزي نفهميديد نگران نباشيد با شكل و مثال متوجه مي شيددر شكل بالا در نيمه اول ما جعبه هاي افقي رو ايجاد كرديم با اين خصوصيات اول اينكه اشيا داراي سايز يكسان نباشند و ديگه اينكه بينشون فاصله نباشه . gtk_hbox_new(FALSE , 0 )خوب حالا به كدي كه براي قرار دادن هر شي در اون جعبه در رديف اول استفاده كرديم توجه كنيد كد:gtk_box_pack_start (GTK_BOX(hbox) , button, FALSE, FALSE, 0) ;خوب در اين كد ما ارگومان سوم رو False كرديم يعني گفتيم كه فضاي اضافي به جعبه اختصاص داده بشه و ارگومان چهارم روهم False كرديم و گفتيم كه اين فضاي خالي باقي مانده براي جعبه باشه .در رديف پايين ترش ما از كد زير استفاده كرديم كد:gtk_box_pack_start (GTK_BOX(hbox) , button, TRUE, FALSE, 0) ;در اين كد ما ارگومان سوم را به TRUE ست كرديم يعني گفتيم كه فضاي خالي باقيمانده به اشيا اختصاص داده بشه بدين شكل كه فضاي خالي باقي مانده جعبه بر تعداد اشيا تقسيم مي شه و هر شي در وسط سهم خودش قرار مي گيره مشاهده مي كنيد كه در اطراف هر شي يك فضاي خالي ايجاد شده . كد رديف پايين ترش بدين شكل هست كد:gtk_box_pack_start (GTK_BOX(hbox) , button, TRUE, TRUE, 0) ;ما ارگومان چهارم رو به TRUE ست كرديم اين يعني چي يعني اينكه بر طبق ارگومان سوم فضاي خالي به شي تخصيص داده شده حالا بر طبق ارگومان چهارم اين فضايي كه به هر شي تخصيص داده شده جزيي از سايز اون شي بشه كه در شكل مشاهده مي كنيد كه ديگه فضاي خالي وجود نداره و اندازه اشيا بزرگ تر شده . خوب در ادامه ما اومديم يك جعبه ايجاد كرديم با خصوصيات زير كه اشيا سايز يكساني داشته باشن و بينشون فاصله نباشه . gtk_hbox_new(TRUE , 0)خوب در رديف اول براي قرار دادن اشيا در اون كد زير رو بكار بستيمكد:gtk_box_pack_start (GTK_BOX(hbox) , button, TRUE, FALSE, 0) ;يعني اين كه فضاي خالي به اشيا داده بشه ولي به سايز اشيا اضافه نشه همون طور كه مي بينيد در اين صورت ديگه اشيا داراي اندازه هاي يكساني نمي شن و ارگومان اول جعبه ما از كار ميفته .در رديف بعدي كد زير رو بكار بستيمكد:gtk_box_pack_start (GTK_BOX(hbox) , button, TRUE, TRUE, 0) ;يعني اينكه فضاي خالي به اشيا اختصاص داده بشه و فضاي اختصاص داده شده جزيي از اندازه اون شي بشه در اينجا چون ارگومان اول جعبه ما به TRUE ست شده اين فضا طوري بين اشيا توزيع مي شه كه همه داراي سايز يكساني شن .خوب ديگه فكر كنم در مورد اين روش بسته بندي ديگه توضيح كافي باشه . اميدوارم مطلب رو فهميده باشيد !!!اموزش gtk قسمت پنجم :ديدم براي بسته بندي با جعبه مثال نزدم اينم مثال مثال :كد:#include gtk/gtk.h int main(int argc , char *argv[]){gtk_init( argc, argv);GtkWidget *window ;GtkWidget *hbox ;GtkWidget *button1;GtkWidget *button2;window= gtk_window_new(GTK_WINDOW_TOPLEVEL);hbox=gtk_hbox_ new(TRUE , 0);gtk_container_add(GTK_CONTAINER(window),hbox);b utton1=gtk_button_new_with_label(“BUTTON 1”);button2=gtk_button_new_with_label(“BUTTON 2”);gtk_box_pack_start (GTK_BOX(hbox) , button1, TRUE, TRUE, 0) ;gtk_box_pack_start (GTK_BOX(hbox) , button2, TRUE, TRUE, 0) ;gtk_widget_show(window);gtk_widget_show(hbox);gtk _widget_show(button1);gtk_widget_show(button2);gtk _main();return 0;}حالا براي اينكه نكته اي رو هم گفته باشم اين رو از من داشته باشيد براي مخفي كردن يك widget در پنجره مي تونيد به جاي استفاده از تابع gtk_widget_show(widget) از تابع gtk_widget_hide(widgt) استفاده كنيد . نكته اي ديگه اينكه وقتي شما داريد راهنماي gtk رو مي خونيد با انواعي رو به رو مي شيد مثل gint يا gchar اينها چي هستن اينها همان انواع معروف int يا char هستن كه براي افزايش قابليت حمل پذيري برنامه ها و براي اينكه بر روي انواع توزيع ها با معماري هاي مختلف قابل اجرا باشند بدين شكل دوباره تعريف شده اند و مال كتابخانه glib هستن كه اون كتابخانه رو هم چون زير مجموعه اين gtk هستن در اينده اي نزديك معرفي مي كنم .رويداد ها مثالكد:#include gtk/gtk.h void hello(GtkWidget *widget , gpointer data ){g_print( WELLCOME TO MY PROGRAM );}int main(int argc , char *argv[]){gtk_init( argc, argv);GtkWidget *window ;GtkWidget *hbox ;GtkWidget *button1;GtkWidget *button2;window= gtk_window_new(GTK_WINDOW_TOPLEVEL);hbox=gtk_hbox_ new(TRUE , 0);gtk_container_add(GTK_CONTAINER(window),hbox);b utton1=gtk_button_new_with_label( BUTTON 1 );button2=gtk_button_new_with_label( BUTTON 2 );gtk_box_pack_start (GTK_BOX(hbox) , button1, TRUE, TRUE, 0) ;gtk_box_pack_start (GTK_BOX(hbox) , button2, TRUE, TRUE, 0) ;g_signal_connect( G_OBJECT(button1) , clicked , G_CALLBACK(hello),NULL) ;g_signal_connect_swapped(G_OBJECT(button1), clicked ,G_CALLBACK(gtk_widget_show) , G_OBJECT(button2));gtk_widget_show(window);gtk_wid get_show(hbox);gtk_widget_show(button1);gtk_main() ;return 0;}قبل از بررسي مثال يه سري مطالب هست كه بايد گفته شه . سيگنال و callbackهر دكمه اي كه فشار داده ميشه هر كليك و امثال اين رويداد ها يك سيگنال ايجاد ميشه و تابع اي كه به اين سيگنال جواب ميده يا به عبارتي مخاطب اين سيگنال هست مي گن callback اين توضيح عاميانه و سادش هست .براي اينكه براي يك widget توليد سيگنال كنيم توابع زيادي وجود داره كه پركاربرد ترين و عام ترين تابع براي اين كار تابع زير مي باشد .كد:g_signal_connect( G_OBJECT(object name) , event name , G_CALLBACK(func) , func data ) ;ارگومام اول يك ابجكت هست كه در واقع نام اون widget هست كه مي خواهيم براي ان يك سيگنال ايجاد كنيم ارگومان دوم رشته اي هست از نوع اشاره گر const gchar * name كه معادل (const char *name) هست و نام رويدادي هست كه مي خواهيم براي ان widget ايجاد كنيم كه ليست رويداد هايي كه مي توانيد براي هر widget استفاده كنيد در راهنماي كتابخانه موجود است من هم سعي مي كنم بيشترش رو بگم ارگومان سوم نام تابعي هست كه مخاطب اين سيگنال ايجاد شده است و ارگومان اخر هم اطلاعاتي هست كه مي خوايم به تابعي كه مخاطب سيگنال هست فرستاده بشه كه از نوع gpointer هست .كه براي ايجاد يك رويداد كليك براي يك دكمه تابعي كه ايجاد اين سيگنال مي كنه مي شه مثل شكل زيركد:g_signal_connect(G_OBGECT(button),”cl icked”,G_CALLBACK(hello) , NULL) ;خوب حالا براي اين سيگنال پارامتر هاي تابع callback بايد به شكل زير باشه كد:void callback_func( GtkWidget *widget, gpointer callback_data );كه پارامتر اول اون widget كه سيگنال رو ايجاد كرده دريافت مي كنه و پارامتر دوم هم براي دريافت اطلاعاتي هست كه توسط ارگومان چهارم تابع سيگنال فرستاده شده .كه مثلا براي مثال قبل تابع callback ميشه به شكل زيركد:Void hello(GtkWidget *widget , gpointer data )خوب يه نوع تابع ديگه اي كه براي توليد سگنال استفاده ميشه تابع زير هست كد:g_signal_connect_swapped(G_OBJECT(object name),”event name“ ,G_CALLBACK(func namr) , G_OBJECT(name2));كه همه ارگومان هاش مثل تابع قبلي هست جز اخرين مورد كه widgt هست كه مي خوايم به تابع بفرستيم . از اين تابع زماني استفاده مي كنيم كه بجاي اون widgt كه براش اين سيگنال رو ساختيم widgt ديگه اي به تابع ارسال بشه مثل وقتي كه دكمه فشار داده ميشه به جاي اينكه دكمه به عنوان پارامتر اول تابع callback ارسال بشه ارگومان چهارم مثلا يك label به تابع callback ارسال ميشه براي اين تابع شكل تابع callback بايد بدين شكل باشه كد:void callback_func( GtkObject *object );كه تنها يك پارامتر داره اون هم شي است كه مقدارش برابر ارگومان چهارم تابع سيگنال هست .خوب ديگه الان مثالي كه براتون زدم همه چيزش براي شما بايد واضح باشه جز تابه g_print كه براي نوشتن يك متن در كنسول ازش استفاده مي شه . داستان رويداد ها هنوز ادامه داره ادامه در پست بعد .در اين قسمت چند تا از توابع ديگه كه مربوط به اين مبحث ميشه رو معرفي مي كنم كد:#define gtk_signal_lookup(name,object_type)كه ارگومان اولش نام رويدادي هست كه شما دنبالش هستيد و ارگومان دوم نوع شي است كه اين سيگنال رو ايجاد كرده كه اگه موفق به پيدا كردن چنين سيگنالي در برنامه نشه مقدار صفر را برمي گرداند مثالكد:Int a=gtk_signal_lookup(“clicked” , GTK_TYPE_BUTTON);كه مقدار برگشتي اين تابع در اينجا a به عنوان signal id شناخته مي شه . كاربرد اين تابع هم در واقع بدست اوردن همين عدد هست كه به عنوان ارگوماني براي توابع ديگه بكار ميره .كد:#define gtk_signal_name(signal_id)خوب اين تابع هم يك ارگومان داره و اون هم سگنال ايدي هست كه توسط تابع قبلي بدست مي ياد و كارش هم اين هست كه نام سيگنالي كه توسط اين ايدي ايجاد ميشه را بر مي گرداند مثلاكد:Const gchar *a= gtk_signal_name(signal_id);كه كاربرد عملي اين تابع هم بيشتر در برنامه هاي بزرگ معلوم ميشه كد:#define g_signal_handler_disconnect (object,handler_id)اين تابع هم براي قطع سيگنال ايجاد شده بكار ميره كه ارگومان اولش اون شي هست كه سيگنال رو ايجاد كرده و ارگومان دومش هم مقدار بازگشتي هست كه از تابع g_signal_connect بدست مي ايد هست . مثلاكد:#include gtk/gtk.h #include iostream using namespace std;int a;void hello(GtkWidget *widget , gpointer data ){g_print( WELCOME TO MY PROGRAM );}void hi( GtkObject *object ){g_signal_handler_disconnect (object,a);}int main(int argc , char *argv[]){gtk_init( argc, argv);GtkWidget *window ;GtkWidget *hbox ;GtkWidget *button1;GtkWidget *button2;window= gtk_window_new(GTK_WINDOW_TOPLEVEL);hbox=gtk_hbox_ new(TRUE , 0);gtk_container_add(GTK_CONTAINER(window),hbox);b utton1=gtk_button_new_with_label( BUTTON 1 );button2=gtk_button_new_with_label( BUTTON 2 );gtk_box_pack_start (GTK_BOX(hbox) , button1, TRUE, TRUE, 0) ;gtk_box_pack_start (GTK_BOX(hbox) , button2, TRUE, TRUE, 0) ; a=g_signal_connect( G_OBJECT(button1) , clicked , G_CALLBACK(hello),NULL) ;g_signal_connect_swapped( G_OBJECT(button2) , clicked , G_CALLBACK(hi),G_OBJECT(button1)) ;gtk_widget_show(window);gtk_widget_show(hbox);gtk _widget_show(button1);gtk_widget_show(button2);gtk _main();return 0;}اول دكمه 1 رو فشار بديد متني در كنسول چاپ ميشه دكمه دو رو فشار بديد از اين لحظه به بعد هر چي دكمه يك رو فشار بديد ديگه كار نمي كنه . كد:#define g_signal_handlers_disconnect_by_func (object,func,data);اين هم كار تابع قبلي رو انجام مي ده فقط ارگومان هاش فرق داره كه ارگومان دوم نام تابعي هست كه مخاطب سيگنال ايجاد شده هست مثلاكد:g_signal_handlers_disconnect_by_func (object , hello , NULL);توابع ديگه اي هم وجود داره كه زياد كاربردي نيستن اونها رو ديگه خودتون بريد تو راهنماي كتابخانه ببينيد .اخرين مطلبي كه در اين مبحث به اون اشاره مي كنم اينه •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اگه تابع callback ما شامل اين رويداد ها باشه براي ايجاد سيگنال براي انها از تابع g_signal_connect استفاده مي كنيم و شكل تابع callback هم بصورت زير ميشه كد:gint callback_func( GtkWidget *widget, GdkEvent *event, gpointer callback_data );كه پارامتر اول نام ان widget هست كه براش اين سيگنال رو ايجاد كرديم و پارامتر اخر هم اطلاعاتي هست كه مي خوايم به تابع ارسال كنيم اما پارامتر دوم مقدارش مي تونه يكي از موارد زير باشه اين كه كدوم به كدوم هست رو وقتي كه دارم تك تك widget ها رو بررسي مي كنم مي گم 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مثلا براي رويداد button_press_event شكل تابع سيگنال مي شه كد:g_signal_connect (G_OBJECT (button), button_press_event , G_CALLBACK (button_press_callback), NULL);و شكل تابع callback مي شه كد:static gint button_press_callback( GtkWidget *widget, GdkEventButton *event, gpointer data );يكي نيست به من كمك كنه تكي ادم خسته مي شه ؟ در ضمن فكر كنم زياد اينجا gtk طرفدار ندارهمثال:كد:#include gtk/gtk.h void hello( GtkWidget *widget, gpointer data ){ g_print ( Hello Worldn );}gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ){ g_print ( delete event occurredn ); return TRUE;}void destroy( GtkWidget *widget, gpointer data ){g_print( destroy event occurred ); gtk_main_quit ();}int main( int argc, char *argv[] ){ GtkWidget *window; GtkWidget *button; gtk_init ( argc, argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (G_OBJECT (window), delete_event , G_CALLBACK (delete_event), NULL); g_signal_connect (G_OBJECT (window), destroy , G_CALLBACK (destroy), NULL); gtk_container_set_border_width (GTK_CONTAINER (window), 10); button = gtk_button_new_with_label ( Hello World ); g_signal_connect (G_OBJECT (button), clicked , G_CALLBACK (hello), NULL); g_signal_connect_swapped (G_OBJECT (button), clicked , G_CALLBACK (gtk_widget_destroy), G_OBJECT (window)); gtk_container_add (GTK_CONTAINER (window), button); gtk_widget_show (button); gtk_widget_show (window); gtk_main (); return 0;}خوب اين هم يك مثال كامل براي رويداد ها بيشتر قسمت هاي اين مثال براي شما بايد اشنا باشه و اما ساير قسمت ها كد:gtk_widget_destroy(widget);اين تابع براي حذف يك widget بكار ميره ولي اگه widget ما يك پنجره باشه براي اجراي كاملش به يك تابع مثل شكل زير نياز داره كد:void destroy( GtkWidget *widget, gpointer data ){ gtk_main_quit ();}چون تابع ما تنها مي تونه اون widget رو حذف كنه ولي نمي تونه حلقه gtk_main رو به پايان برسونه وقتي اين تابع اجراي ميشه مقداري رو بر مي گردونه كه بر اساس ان تابع destroy وارد عمل ميشه براي امتحان هم كه شده شما تابع destroy رو از برنامه حذف كنيد مشاهده مي كنيد كه با اجراي برنامه و كليك دكمه ظاهرا پنچره حذف و برنامه خاتمه مي يابد ولي پنجره كنسول هنوز باز هست و اماده دريافت اطلاعات هست علتش هم اين هست كه ما هنوز از حلقه gtk_main خارج نشديم از تابع زير براي خروج از حلقه استفاده مي كنيم كد:gtk_main_quit ();خوب تابع ديگه اي كه تو برنامه داريم كد:gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ){ g_print ( delete event occurredn ); return TRUE;}كه چون ما از رويداد delete_event استفاده كرديم به همين علت تابع callback ما به شكل بالا هست و مقدار بازگشتي اين تابع TRUE يا FALSE هست كه اگه TRUE باشه ديگه تابع destroy اجرا نمي شه اما اگه FALSE باشه موجب اجراي تابع destroy و خروج از برنامه ميشه تابع delete_event هنگامي فراخواني ميشه كه شما دكمه close برنامه رو فشار بديد توجه داشته باشيد كه تابع destroy يا زماني كه شما دكمه موجود در برنامه رو فشار بديد و يا زماني كه شما دكمه close برنامه رو فشار بديد اجرا ميشه با اين مثال قضيه رويداد ها تموم شد هر widget رويداد هاي خاص خودش رو داره و شما هم مي تونيد خودتون يك widget يا يك رويداد جديد بسازيد كه در اينده اون ها رو هم توضيح مي دم .