في هذه الجزء من دورة ال GTK+ , سوف نعمل علي القوائم وشرائط الادوات .
شريط القائمه هو احد الاجزاء العامه في تطبيق ذو واجهة رسوميه . حيث انها مجموعه من الاوامر تقع في شرائط قوائم مختلفه . بينما في برنامج الكونسول يجب عليك ان تتذكر هذه الاوامر الغامضه , هنا لدينا معظم الاوامر مجمعه في اجزاء منطقيه.
في مقالنا الاول , سوف نقوم بانشاء شريط قائمه جديد يحتوي علي قائمة file واحده . سوف تحتوي القائمه علي عنصر واحد . ينغلق البرنامج بمجرد اختيار هذه العنصر من القائمه .
#include <gtk/gtk.h> int main( int argc, char *argv[]) { GtkWidget *window; GtkWidget *vbox; GtkWidget *menubar; GtkWidget *filemenu; GtkWidget *file; GtkWidget *quit; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(window), 250, 200); gtk_window_set_title(GTK_WINDOW(window), "menu"); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); menubar = gtk_menu_bar_new(); filemenu = gtk_menu_new(); file = gtk_menu_item_new_with_label("File"); quit = gtk_menu_item_new_with_label("Quit"); gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), filemenu); gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), quit); gtk_menu_shell_append(GTK_MENU_SHELL(menubar), file); gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 3); g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(G_OBJECT(quit), "activate", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show_all(window); gtk_main(); return 0; }
انشاء شريط القوائم مربك قليلا. لابد ان نضع في اذهاننا ان كل من شريط القوائم والقوائم نفسها منشقين من نفس ال widget , مسمي menu shell . عناصر القوائم صالحة فقط لكي تكون child للقوائم . ويتم استخدامها ايضا لكي نقوم بعمل قوائم فرعيه .
menubar = gtk_menu_bar_new(); filemenu = gtk_menu_new();
في هذه الشفره نقوم بانشاء شريط قوائم جديد ونقوم بانشاء قائمه ايضا .
gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), filemenu);في هذه الشفره نقوم بتنفيذ قائمة file menu . المنطق في هذه الامر هو ان ال menubar هي menu shell . وايضا file menu يعد menu shell . لهذا ننظر علي ال file menu علي انها submenu او subshell .
gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), quit); gtk_menu_shell_append(GTK_MENU_SHELL(menubar), file);
عنصار القائمه تطبق بواسطة استدعاء الداله gtk_menu_shell_append() . عناصر القائمه تربط بال menu shells . في حالتنا , العنصر "quit menu" يتم ربطه بقائمة file "file menu " وايضا ال "file menu" يتم ربطها بشريط القائمه "menu bar " .
g_signal_connect(G_OBJECT(quit), "activate", G_CALLBACK(gtk_main_quit), NULL);
بواسطة اختيار عنصر القائمه , نخرج من البرنامج ويتم غلقه.
Figure: Simple menu
في المثال التالي , سوف نتقدم في اكتشاف الوظائف والخصائص التي نستطيع استخدامها في GTK+ . اختصارات القوائم التي تدعي (Accelerators ) هي اختصارات من لوحة المفاتيح لتفعيل عنصر من قائمه. بينما اختصارات الاحداث والتي تدعي (Mnemonics) فهي اختصارات من لوحة المفاتيح ايضا ولكن للعناصر الخاصه بالوجهه الرسوميه . وهم مقدمين من المستويات المنخفضه .
#include <gtk/gtk.h> #include <gdk/gdkkeysyms.h> int main( int argc, char *argv[]) { GtkWidget *window; GtkWidget *vbox; GtkWidget *menubar; GtkWidget *filemenu; GtkWidget *file; GtkWidget *new; GtkWidget *open; GtkWidget *quit; GtkWidget *sep; GtkAccelGroup *accel_group = NULL; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(window), 250, 200); gtk_window_set_title(GTK_WINDOW(window), "menu"); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); menubar = gtk_menu_bar_new(); filemenu = gtk_menu_new(); accel_group = gtk_accel_group_new(); gtk_window_add_accel_group(GTK_WINDOW(window), accel_group); file = gtk_menu_item_new_with_mnemonic("_File"); new = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL); open = gtk_image_menu_item_new_from_stock(GTK_STOCK_OPEN, NULL); sep = gtk_separator_menu_item_new(); quit = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, accel_group); gtk_widget_add_accelerator(quit, "activate", accel_group, GDK_q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), filemenu); gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), new); gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), open); gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), sep); gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), quit); gtk_menu_shell_append(GTK_MENU_SHELL(menubar), file); gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 3); g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(G_OBJECT(quit), "activate", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show_all(window); gtk_main(); return 0; }
هذه المثال يوضح كيف تقوم باضافة صوره لعنصر من القائمه . وكيف تقوم بانشاء اختصار للقوائم واختصار للعناصر الرسوميه في تطبيق GTK+ .
accel_group = gtk_accel_group_new(); gtk_window_add_accel_group(GTK_WINDOW(window), accel_group); ... quit = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, accel_group); gtk_widget_add_accelerator(quit, "activate", accel_group, GDK_q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
مجموعة الاختصارات هي عباره عن مجموعه من اختصارات في لوحة المفاتيح , نموذجيا مربوطين بنافذه من النوع toplevel . هنا قمنا بانشاء اختصار لقائمه من المفاتيح Ctrl+q .
file = gtk_menu_item_new_with_mnemonic("_File");كي نقوم بانشاء اختصار لعناصر رسوميه , نقوم باستدعاء الداله gtk_menu_item_new_with_mnemonic() . ثم نقوم بتحديد ال file menu بواسطة ضغط Alt + F .
new = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL); open = gtk_image_menu_item_new_from_stock(GTK_STOCK_OPEN, NULL);
هنا نقوم بانشاء صورتين لعنصرين في قائمه . بوساطة ضبط ال parameter الثاني للداله ب NULL , نقوم تلقائيا بعمل اختصار قائمي . ونقدم ايضا صورة واسم للعنصر من المصادر الداخليه ل GTK+ .
sep = gtk_separator_menu_item_new();عناصر القائمه يمكن ان تفصل عن بعضها بواسطة فاصل افقي . بهذه الطريقه يمكن ان نضع عناصر القائمه في مجموعات منطقيه توضح هدف واحد . واضح من الصوره .
Figure: Menu example
GtkCheckMenuItem هو عنصر قائمه بمربع لوضع علامة (Check box) .
#include <gtk/gtk.h> void toggle_statusbar(GtkWidget *widget, gpointer statusbar) { if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) { gtk_widget_show(statusbar); } else { gtk_widget_hide(statusbar); } } int main( int argc, char *argv[]) { GtkWidget *window; GtkWidget *vbox; GtkWidget *menubar; GtkWidget *viewmenu; GtkWidget *view; GtkWidget *tog_stat; GtkWidget *statusbar; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(window), 250, 200); gtk_window_set_title(GTK_WINDOW(window), "view statusbar"); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); menubar = gtk_menu_bar_new(); viewmenu = gtk_menu_new(); view = gtk_menu_item_new_with_label("View"); tog_stat = gtk_check_menu_item_new_with_label("View Statusbar"); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(tog_stat), TRUE); gtk_menu_item_set_submenu(GTK_MENU_ITEM(view), viewmenu); gtk_menu_shell_append(GTK_MENU_SHELL(viewmenu), tog_stat); gtk_menu_shell_append(GTK_MENU_SHELL(menubar), view); gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 3); statusbar = gtk_statusbar_new(); gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, TRUE, 1); g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(G_OBJECT(tog_stat), "activate", G_CALLBACK(toggle_statusbar), statusbar); gtk_widget_show_all(window); gtk_main(); return 0; }
في المثال السابق عرضنا عنصر قائمه علامي (Check menu item) . اذا كان الصندوق مفعل , يتم اظهار شريط الحالة , اذا لم يكن مفعل فان شريط الحاله يختفي .
tog_stat = gtk_check_menu_item_new_with_label("View Statusbar");الداله gtk_check_menu_item_new_with_label() استدعائها ينشئ عنصر قائمه علامي جديد .
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) { gtk_widget_show(statusbar); } else { gtk_widget_hide(statusbar); }
اذا كان الصندوق العلامي مفعل , نقوم باظهار شريط الحاله . غير ذلك فأن شريط الحاله يختفي .
Figure: Check menu item
القوائم تقوم بتجميع الاوامر التي يمكننا استخدامها في تطبيقنا . اما شريط الادوات فهو يوفر حصول سريع علي معظم الاوامر التي نستخدمها بشكل متكرر .
#include <gtk/gtk.h> int main( int argc, char *argv[]) { GtkWidget *window; GtkWidget *vbox; GtkWidget *toolbar; GtkToolItem *new; GtkToolItem *open; GtkToolItem *save; GtkToolItem *sep; GtkToolItem *exit; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(window), 250, 200); gtk_window_set_title(GTK_WINDOW(window), "toolbar"); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); toolbar = gtk_toolbar_new(); gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS); gtk_container_set_border_width(GTK_CONTAINER(toolbar), 2); new = gtk_tool_button_new_from_stock(GTK_STOCK_NEW); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), new, -1); open = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), open, -1); save = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), save, -1); sep = gtk_separator_tool_item_new(); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), sep, -1); exit = gtk_tool_button_new_from_stock(GTK_STOCK_QUIT); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), exit, -1); gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 5); g_signal_connect(G_OBJECT(exit), "clicked", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show_all(window); gtk_main(); return 0; }
هذا المثال يقوم بانشاء شريط ادوات بسيط.
toolbar = gtk_toolbar_new(); gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS)
الان نقوم بانشاء شريط ادوات جديد . نقوم بالتحديد ان الزرائر الموجوده في شريط الادوات تظهر فقط صور وليس كتابات.
new = gtk_tool_button_new_from_stock(GTK_STOCK_NEW); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), new, -1);
نقوم بعمل زرار لشريط الادوات من صوره موجوده في المخزن . زرائر شريط الادوات يتم اضافتها للشريط بواسطة استدعاء الداله gtk_toolbar_insert() .
sep = gtk_separator_tool_item_new(); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), sep, -1);
هنا نقوم بوضع فاصل في شريط الادوات , كما هو واضح من الصوره .
Figure: Toolbar
المثال الاتي يشرح , كيف يمكننا ان تعطيل زرائر موجوده في شريط الادوات . هذا اسلوب مستخدم بكثره في برمجة الواجهات الرسوميه . كمثال زرار الحفظ , اذا قمنا بحفظ تغيرات علي مستند لدينا , فان زرار الحفظ سوف يتم تعطيله . بهذه الطريقه يبلغ التطبيق للمستخدم ان كل التغيرات قد تم حفظها بالفعل .
#include <gtk/gtk.h> #include <string.h> void undo_redo(GtkWidget *widget, gpointer item) { static int count = 2; const char *name = gtk_widget_get_name(widget); if ( strcmp(name, "undo") ) { count++; } else { count--; } if (count < 0) { gtk_widget_set_sensitive(widget, FALSE); gtk_widget_set_sensitive(item, TRUE); } if (count > 5) { gtk_widget_set_sensitive(widget, FALSE); gtk_widget_set_sensitive(item, TRUE); } } int main( int argc, char *argv[]) { GtkWidget *window; GtkWidget *vbox; GtkWidget *toolbar; GtkToolItem *undo; GtkToolItem *redo; GtkToolItem *sep; GtkToolItem *exit; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(window), 250, 200); gtk_window_set_title(GTK_WINDOW(window), "undoredo"); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); toolbar = gtk_toolbar_new(); gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS); gtk_container_set_border_width(GTK_CONTAINER(toolbar), 2); undo = gtk_tool_button_new_from_stock(GTK_STOCK_UNDO); gtk_widget_set_name(GTK_WIDGET(undo), "undo"); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), undo, -1); redo = gtk_tool_button_new_from_stock(GTK_STOCK_REDO); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), redo, -1); sep = gtk_separator_tool_item_new(); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), sep, -1); exit = gtk_tool_button_new_from_stock(GTK_STOCK_QUIT); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), exit, -1); gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 5); g_signal_connect(G_OBJECT(undo), "clicked", G_CALLBACK(undo_redo), redo); g_signal_connect(G_OBJECT(redo), "clicked", G_CALLBACK(undo_redo), undo); g_signal_connect(G_OBJECT(exit), "clicked", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show_all(window); gtk_main(); return 0; }
مثالنا يقوم بإنشاء زرارين اعد / الغي الفعل undo/redo من المصادر المخزنه في GTK+ (stock resources ) . بعد عدة ضغطات علي الزرار سوف يتم تعطيله . ويتغير لونها الي اللون الرمادي .
if (count < 0) { gtk_widget_set_sensitive(widget, FALSE); gtk_widget_set_sensitive(item, TRUE); } if (count > 5) { gtk_widget_set_sensitive(widget, FALSE); gtk_widget_set_sensitive(item, TRUE); }
الدالة gtk_widget_set_sensitive() يتم استخدامها لتفعيل/تعطيل زرائر موجوده في شريط الادوات .
Figure: Undo redo
Home Contents Top of Page