# Native Code > برنامه نویسی با C > برنامه نویسی GTK، GTK+‎ و wxWidget >  اموزش برنامه نویسی با gtk

## hamid206

کار رو با یک مثال ساده شروع می کنم در این مثال مطالبی مطرح میشه که در بیشتر برنامه ها یی که بعدا می نویسیم استفاده می شه 
مثال اول
#include <gtk/gtk.h>
int main(int argc , char *argv[] ) {
GtkWidget  *window ;
gtk_init( &argc , &argv);
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_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 در ویندوز و پیکربندی ان برای کامپایل برنامه ها با ویژوال سی پلاس پلاس

اگه همه کار ها رو درست انجام داده باشید باید زمانی که برنامه خود را اجرا می کنید مثل شکل پایین باشه

----------


## hamid206

مثال دوم 
در مثال قبل شما ساختار کلی یک برنامه رو که از 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_CONTAINER(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(button);

اگه بخوایم بر روی دکمه ای که ایجاد می کنیم مطلبی نوشته باشد می تونیم از تابع gtk_button_new_with_label(“string”) استفاده کنیم که بر این اساس کد های بالا بدین شکل میشه
GtkWidget  *button;
button=gtk_button_new_with_label(“Welcome”);
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),”Welcome  ”);
و با استفاده از تابع زیر هم می تونید خاصیت resize پنجره رو فعال یا غیر فعال کنید
gtk_window_set_resizable(GTK_WINDOW(name),Boolean)  ;
که مثلا اگه بخوایم در  پنجره مثال دوم ما خاصیت resize غیر فعال بشه کد ما میشه این
gtk_window_set_resizable(GTK_WINDOW(window),FALSE)  ;
برای تعیین اندازه پنجره هم می تونید از تابع زیر استفاده کنید 
gtk_widget_set_size_request(GTK_WIDGET(name),width  ,hight);
خوب برگردیم به مثال دوم در اونجا یه خط کد هست که هنوز توضیح ندادم 
gtk_container_add(GTK_CONTAINER(window),button);
خوب با استفاده از این تابع به gtk می گیم که دکمه ما رو در درون پنجره قرار بده . این تابع تنها می تونه یک widget رو در پنجره قرار بده و اگه شما دوتا دکمه داشته باشید این تابع دیگه جواب گو نیست و باید از روشی به نام بسته بندی کردن widget استفاده کنیم که در پست بعدی به بیان اون می پردازم .

----------


## hamid206

وقتی که ما یک برنامه کاربردی ایجاد می کنیم عمدتا بیش از یک 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(name) , 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_table_new(1,2,FALSE);
gtk_container_add(GTK_CONTAINER(window),table);
button1=gtk_button_new_with_label(“BUTTON 1”);
button2=gtk_button_new_with_label(“BUTTON 2”);
gtk_table_attach_defaults(GTK_TABLE(table),button1  ,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(button2);
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);

----------


## hamid206

روش دوم بسته بندی 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 ست شده این فضا طوری بین اشیا توزیع می شه که همه دارای سایز یکسانی شن .
خوب دیگه فکر کنم در مورد این روش بسته بندی دیگه توضیح کافی باشه . امیدوارم مطلب رو فهمیده باشید !!!

----------


## hamid206

اموزش 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);
button1=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 هستن در اینده ای نزدیک معرفی می کنم .

----------


## hamid206

رویداد ها 
مثال
#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);
button1=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),"clicke  d"  ,G_CALLBACK(gtk_widget_show) , G_OBJECT(button2));
gtk_widget_show(window);
gtk_widget_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),”clicked”,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 که برای نوشتن یک متن در کنسول ازش استفاده می شه . داستان رویداد ها هنوز ادامه داره ادامه در پست بعد .

----------


## hamid206

در این قسمت چند تا از توابع دیگه که مربوط به این مبحث میشه رو معرفی می کنم 
#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);
button1=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 طرفدار نداره

----------


## hamid206

مثال:
#include <gtk/gtk.h>

void hello( GtkWidget *widget,
            gpointer   data )
{
    g_print ("Hello World\n");
}

gint delete_event( GtkWidget *widget,
                   GdkEvent  *event,
		   gpointer   data )
{
  
    g_print ("delete event occurred\n");
  
    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 occurred\n");
  
    return TRUE;
}

که چون ما از رویداد delete_event استفاده کردیم به همین علت تابع callback ما به شکل بالا هست و مقدار بازگشتی این تابع TRUE یا FALSE هست که اگه TRUE باشه دیگه تابع destroy اجرا نمی شه اما اگه FALSE باشه موجب اجرای تابع destroy و خروج از برنامه میشه تابع delete_event هنگامی فراخوانی میشه که شما دکمه close برنامه رو فشار بدید  توجه داشته باشید که تابع destroy یا زمانی که شما دکمه موجود در برنامه رو فشار بدید و یا زمانی که شما دکمه close برنامه رو فشار بدید اجرا میشه با این مثال قضیه رویداد ها تموم شد هر widget رویداد های خاص خودش رو داره و شما هم می تونید خودتون یک widget یا یک رویداد جدید بسازید که در اینده اون ها رو هم توضیح می دم .

----------


## ravand

ببخشید این مقاله نحوه نصب gtk در ویندوز و پیکربندی ان برای کامپایل برنامه ها با ویژوال سی پلاس پلاس لینکش کجاست؟

----------

