Home  Contents

GTK+ layout management

في هذه الفصل سوف نشرح كيف تقوم باضافة widgets  في نافذه او dialogs  .

عندما نقوم ببناء واجهة رسوميه لتطبيقنا , نقرر ماهي ال wigets  التي سوف نستخدمها وكيف نقوم بترتيبها.لكي نستطيع ان نتحكم في ترتيب هذه ال widgets   نستخدم نوع خاص اخر من ال widgets   يسمي layout container  وعاء بمعني اصح . في هذه الفصل , سوف نذكر GtkAlignment , GtkFixed , GtkVBox  و GtKTable  .

GtkFixed

وعاء GtkFixed يقوم بوضع الchild widgets في اماكن محدده بمساحات محدده . هذه الوعاء لا يقوم بأي ادارة لل layouts . في معظم التطبيقات لا نقوم باستخدام GtkFixed . في بعض الحالات الخاصه نقوم باستخدام هذه النوع من الوعاء.كمثال اللالعاب , التطبيقات المميزه التي تعمل مع الرسوم البيانيه عناصر يمكن ان تتغير مساحتها او تنقل مثل جدول بياني في  تطبيق يستخدم spreadsheet .



#include <gtk/gtk.h>


int main( int argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *fixed;

  GtkWidget *button1;
  GtkWidget *button2;
  GtkWidget *button3;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "GtkFixed");
  gtk_window_set_default_size(GTK_WINDOW(window), 290, 200);
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

  fixed = gtk_fixed_new();
  gtk_container_add(GTK_CONTAINER(window), fixed);

  button1 = gtk_button_new_with_label("Button");
  gtk_fixed_put(GTK_FIXED(fixed), button1, 150, 50);
  gtk_widget_set_size_request(button1, 80, 35);

  button2 = gtk_button_new_with_label("Button");
  gtk_fixed_put(GTK_FIXED(fixed), button2, 15, 15);
  gtk_widget_set_size_request(button2, 80, 35);

  button3 = gtk_button_new_with_label("Button");
  gtk_fixed_put(GTK_FIXED(fixed), button3, 100, 100);
  gtk_widget_set_size_request(button3, 80, 35);

  g_signal_connect_swapped(G_OBJECT(window), "destroy", 
      G_CALLBACK(gtk_main_quit), NULL);

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}

في مثالنا , قمنا بانشاء ثلاث زراير وقمنا بوضعه في موقع ثابت . حيث اننا عندما نقوم بتغير حجم نافذة هذا التطبيق , الزراير تظل محتفظه بحجمها ومكانها .

 fixed = gtk_fixed_new();

هنا قمنا بإنشاء وعاء من نوع GtkFixed .

 gtk_fixed_put(GTK_FIXED(fixed), button1, 150, 50);

اول زرار يتم اضافته ووضعه بالداله gtk_fixed_put()   بخط طول وعرض x=150 y =50  .




GtkFixed container

Figure: GtkFixed container



GtkVBox

الوعاء GtkVBox هو وعاء عمودي . يقوم بوضع ال childs  الخاصه به في عمود واحد . GtkHBox هو نفس الوعاء ولكن هذا الوعاء يقوم بوضع ال childs  الخاصه به في صف واحد .



#include <gtk/gtk.h>


int main( int argc, char *argv[])
{

  GtkWidget *window;
  GtkWidget *vbox;

  GtkWidget *settings;
  GtkWidget *accounts;
  GtkWidget *loans;
  GtkWidget *cash;
  GtkWidget *debts;

  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), 230, 250);
  gtk_window_set_title(GTK_WINDOW(window), "GtkVBox");
  gtk_container_set_border_width(GTK_CONTAINER(window), 5);

  vbox = gtk_vbox_new(TRUE, 1);
  gtk_container_add(GTK_CONTAINER(window), vbox);

  settings = gtk_button_new_with_label("Settings");
  accounts = gtk_button_new_with_label("Accounts");
  loans = gtk_button_new_with_label("Loans");
  cash = gtk_button_new_with_label("Cash");
  debts = gtk_button_new_with_label("Debts");

  gtk_box_pack_start(GTK_BOX(vbox), settings, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), accounts, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), loans, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), cash, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), debts, TRUE, TRUE, 0);

  g_signal_connect_swapped(G_OBJECT(window), "destroy",
        G_CALLBACK(gtk_main_quit), G_OBJECT(window));

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}

هذا مثال بسيط يعرض GtkVBox . يقوم بجمع 5 زراير في صف واحد . اذا قمنا بتغير حجم نافذة التطبيق يتم تغير حجم الزراير ايضا حيث انهم child widgets ل GtkVBox .

 vbox = gtk_vbox_new(TRUE, 1);

تم انشاء GtkVBox . نقوم بوضع الparameter الذي يحدد اذا ماكان العناصر الداخله لهذا الصندوق  متجانسه ام لا ونضعه بالقيمه TRUE  اي حقيقي . هذا يعني ان كل الزراير الموجوده سوف تكون بحجم واحد . اما بالنسبه للمسافات بين ال widgets داخل الصندوق فنقوم بوضعها ل 1 .

gtk_box_pack_start(GTK_BOX(vbox), settings, TRUE, TRUE, 0);

نقوم بتعليب الزرار (setting) داخل الوعاء . اول اثنان parameter هم الوعاء وال child widget   اي الزرار (setting) . الثلاث parameters الاخري هم , expand  اي وسع ,  fill  اي املأ , padding  اي حشو الفراغ . لاحظ ان parameter  الملأ fill ليه لسه تأثير , اذا كان ال expand parameter  قيمته FALSE  اي غير حقيقي . وعلي نفس النمط لن يكون لل expand parameter اي تأثير اذا قمنا بانشاء الصندوق من البدايه ووضعنا parameter  التجانس homogenous الي القيمه حقيقي TRUE .ٌTRUE.


GtkVBox container

Figure: GtkVBox container



GtkTable

يقوم هذه ال Widget المسمي ب GtkTable  بوضع العناصر في صفوف واعمده .كما هو واضح من الاسم .

#include <gtk/gtk.h>


int main( int argc, char *argv[])
{

  GtkWidget *window;

  GtkWidget *table;
  GtkWidget *button;

  char *values[16] = { "7", "8", "9", "/", 
     "4", "5", "6", "*",
     "1", "2", "3", "-",
     "0", ".", "=", "+"
  };

  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, 180);
  gtk_window_set_title(GTK_WINDOW(window), "GtkTable");

  gtk_container_set_border_width(GTK_CONTAINER(window), 5);

  table = gtk_table_new(4, 4, TRUE);
  gtk_table_set_row_spacings(GTK_TABLE(table), 2);
  gtk_table_set_col_spacings(GTK_TABLE(table), 2);

  int i = 0;
  int j = 0;
  int pos = 0;

  for( i=0; i < 4; i++) {
    for( j=0; j < 4; j++) {
      button = gtk_button_new_with_label(values[pos]);
      gtk_table_attach_defaults(GTK_TABLE(table), button, j, j+1, i, i+1 );
      pos++;
    }
  }

  gtk_container_add(GTK_CONTAINER(window), table);

  g_signal_connect_swapped(G_OBJECT(window), "destroy",
        G_CALLBACK(gtk_main_quit), G_OBJECT(window));

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}

في هذا المثال نقوم بانشاء مجموعه من الزراير التي يمكن ان نراها في الة حاسبه .

 table = gtk_table_new(4, 4, TRUE);

نقوم بانشاء Widget   جديد من النوع  GtkTable  ونقوم باعطائه 4 اعمده و 4 صفوف .

 gtk_table_set_row_spacings(GTK_TABLE(table), 2);
 gtk_table_set_col_spacings(GTK_TABLE(table), 2);

نقوم بوضع بعض المساحات بين كل صف وكل عمود . واضح من استخدام الدوال.

 for( i=0; i < 4; i++) {
   for( j=0; j < 4; j++) {
     button = gtk_button_new_with_label(values[pos]);
     gtk_table_attach_defaults(GTK_TABLE(table), button, j, j+1, i, i+1 );
     pos++;
   }
 }

هنا نقوم بانشاء 16 زرار ونقوم بتعليبهم داخل الواعاء الجدولي GtkTable .


GtkTable container

Figure: GtkTable container



GtkAlignment

هذا الوعاء المسمي ب GtkAlignment  يقوم بضبط الانحياز والحجم لاطفاله child widgets  .t.

#include <gtk/gtk.h>


int main( int argc, char *argv[])
{

  GtkWidget *window;
  GtkWidget *ok;
  GtkWidget *close;

  GtkWidget *vbox;
  GtkWidget *hbox;
  GtkWidget *halign;
  GtkWidget *valign;

  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), 350, 200);
  gtk_window_set_title(GTK_WINDOW(window), "GtkAlignment");
  gtk_container_set_border_width(GTK_CONTAINER(window), 10);

  vbox = gtk_vbox_new(FALSE, 5);

  valign = gtk_alignment_new(0, 1, 0, 0);
  gtk_container_add(GTK_CONTAINER(vbox), valign);
  gtk_container_add(GTK_CONTAINER(window), vbox);

  hbox = gtk_hbox_new(TRUE, 3);

  ok = gtk_button_new_with_label("OK");
  gtk_widget_set_size_request(ok, 70, 30);
  gtk_container_add(GTK_CONTAINER(hbox), ok);
  close = gtk_button_new_with_label("Close");
  gtk_container_add(GTK_CONTAINER(hbox), close);

  halign = gtk_alignment_new(1, 0, 0, 0);
  gtk_container_add(GTK_CONTAINER(halign), hbox);

  gtk_box_pack_start(GTK_BOX(vbox), halign, FALSE, FALSE, 0);

  g_signal_connect_swapped(G_OBJECT(window), "destroy",
        G_CALLBACK(gtk_main_quit), G_OBJECT(window));

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}

في هذا المثال , نقوم بوضع زرارين داخل الركن اليميني في النافذه . لكي نصل الي هذا , نقوم باستخدام صندوق افقي واحد horizontal box وصندوق عمودي واحد vertical box ووعائين انحيازيين alignment containers  .



 valign = gtk_alignment_new(0, 1, 0, 0);

سوف نقوم بوضع ال widget   الطفل في الاسفل .

 gtk_container_add(GTK_CONTAINER(vbox), valign);

هنا نضع الوعاء الانحيازي في الصندوق العمودي .

 hbox = gtk_hbox_new(TRUE, 3);

 ok = gtk_button_new_with_label("OK");
 gtk_widget_set_size_request(ok, 70, 30);
 gtk_container_add(GTK_CONTAINER(hbox), ok);
 close = gtk_button_new_with_label("Close");
 gtk_container_add(GTK_CONTAINER(hbox), close);

نقوم بإنشاء صنوق افقي ونضع زرارين فيه.

 halign = gtk_alignment_new(1, 0, 0, 0);
 gtk_container_add(GTK_CONTAINER(halign), hbox);

 gtk_box_pack_start(GTK_BOX(vbox), halign, FALSE, FALSE, 0);

هذا الكود سوف ينشئ وعاء انحيازي alignment container الذي يضع اطفاله في اليمين . ثم نقوم بوضع الصندوق الافقي في الوعاء الانحيازي ثم نقوم بتعليب الوعاء الانحيازي داخل الصندوق العمودي . يجب ان نضع في اذهاننا ان الوعاء الانحيازي alignment container  يأخذ طفل واحد . ولهذا يجب ان نستخدم الصناديق .


GtkAlignment container

Figure: GtkAlignment container



Windows

في المثال الاتي سوف نقوم بانشاء مثال اكثر تقدما . سوف نعرض نافذه يمكن ان تجدها في بيئة تطوير برمجيه للغه java  . اي واحده مثلها وليست هي ونحن نقوم بذلك كي نريك بعض الاشياء المتقدمه الخاصه بالنافذه .


Windows dialog in JDeveloper

Figure: Windows dialog in JDeveloper



هذا المربع الحواري يعرض كل الشرائط المفتوحه في بيئة التطوير البرمجيه لتطبيق (Jdeveloper ) .

#include <gtk/gtk.h>



int main( int argc, char *argv[])
{

  GtkWidget *window;
  GtkWidget *table;

  GtkWidget *title;
  GtkWidget *activate;
  GtkWidget *halign;
  GtkWidget *halign2;

  GtkWidget *valign;
  GtkWidget *close;
  GtkWidget *wins;

  GtkWidget *help;
  GtkWidget *ok;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_widget_set_size_request (window, 300, 250);
  gtk_window_set_resizable(GTK_WINDOW(window), FALSE);

  gtk_window_set_title(GTK_WINDOW(window), "Windows");

  gtk_container_set_border_width(GTK_CONTAINER(window), 15);

  table = gtk_table_new(8, 4, FALSE);
  gtk_table_set_col_spacings(GTK_TABLE(table), 3);

  title = gtk_label_new("Windows");
  halign = gtk_alignment_new(0, 0, 0, 0);
  gtk_container_add(GTK_CONTAINER(halign), title);
  gtk_table_attach(GTK_TABLE(table), halign, 0, 1, 0, 1, 
      GTK_FILL, GTK_FILL, 0, 0);

  wins = gtk_text_view_new();
  gtk_text_view_set_editable(GTK_TEXT_VIEW(wins), FALSE);
  gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(wins), FALSE);
  gtk_table_attach(GTK_TABLE(table), wins, 0, 2, 1, 3,
      GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 1, 1);

  activate = gtk_button_new_with_label("Activate");
  gtk_widget_set_size_request(activate, 50, 30);
  gtk_table_attach(GTK_TABLE(table), activate, 3, 4, 1, 2, 
      GTK_FILL, GTK_SHRINK, 1, 1);

  valign = gtk_alignment_new(0, 0, 0, 0);
  close = gtk_button_new_with_label("Close");
 
  gtk_widget_set_size_request(close, 70, 30);
  gtk_container_add(GTK_CONTAINER(valign), close);
  gtk_table_set_row_spacing(GTK_TABLE(table), 1, 3);
  gtk_table_attach(GTK_TABLE(table), valign, 3, 4, 2, 3, 
      GTK_FILL, GTK_FILL | GTK_EXPAND, 1, 1);

  halign2 = gtk_alignment_new(0, 1, 0, 0);
  help = gtk_button_new_with_label("Help");
  gtk_container_add(GTK_CONTAINER(halign2), help);
  gtk_widget_set_size_request(help, 70, 30);
  gtk_table_set_row_spacing(GTK_TABLE(table), 3, 6);
  gtk_table_attach(GTK_TABLE(table), halign2, 0, 1, 4, 5, 
      GTK_FILL, GTK_FILL, 0, 0);

  ok = gtk_button_new_with_label("OK");
  gtk_widget_set_size_request(ok, 70, 30);
  gtk_table_attach(GTK_TABLE(table), ok, 3, 4, 4, 5, 
      GTK_FILL, GTK_FILL, 0, 0);

  gtk_container_add(GTK_CONTAINER(window), table);

  g_signal_connect_swapped(G_OBJECT(window), "destroy",
        G_CALLBACK(gtk_main_quit), G_OBJECT(window));

  gtk_widget_show_all(window);
  gtk_main();

  return 0;
}

هذا الكود يعرض كيف يممكنا ان نصنع نافذه مماثله في GTK+ .

 table = gtk_table_new(8, 4, FALSE);

نقوم باستخدام وعاء جدولي .

 title = gtk_label_new("Windows");
 halign = gtk_alignment_new(0, 0, 0, 0);
 gtk_container_add(GTK_CONTAINER(halign), title);
 gtk_table_attach(GTK_TABLE(table), halign, 0, 1, 0, 1, 
     GTK_FILL, GTK_FILL, 0, 0);

هذا الكود يقوم بعمل عنوان نصي (label) منحاز الي الشمال . هذا العنوان النصي موضوع في الصف الاول في الوعاء الجدولي GtkTable .

 wins = gtk_text_view_new();
 gtk_text_view_set_editable(GTK_TEXT_VIEW(wins), FALSE);
 gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(wins), FALSE);
 gtk_table_attach(GTK_TABLE(table), wins, 0, 2, 1, 3, 
     GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 1, 1);

هذا ال text view widget  خاص بعرض النصوص يمتد مسافه عمودين وصفين . ثم نقوم باعطاء خاصية عدم التعديل وتعطيل الفأره داخل هذا ال widget .

 valign = gtk_alignment_new(0, 0, 0, 0);
 close = gtk_button_new_with_label("Close");
 
 gtk_widget_set_size_request(close, 70, 30);
 gtk_container_add(GTK_CONTAINER(valign), close);
 gtk_table_set_row_spacing(GTK_TABLE(table), 1, 3);
 gtk_table_attach(GTK_TABLE(table), valign, 3, 4, 2, 3, 
     GTK_FILL, GTK_FILL | GTK_EXPAND, 1, 1);

نقوم بوضع زرار الاغلاق بجانب صندوق عرض النصوص text view widget في الصف العمود الرابع . نقوم بوضع هذا الزرار في alignment widget  لكي نستطيع ان نجعله منحاز الي الاعلي .


Windows

Figure: Windows


Home ‡ Contents ‡ Top of Page