构建用户界面

当我们构建一个更加复杂的带有成百控件的用户界面时,用C程序做这些控件的所有设置工作是非常麻烦的,而且也让做些调整变得几乎不可能。
谢天谢地, GTK+ 支持将用户界面布局从业务逻辑中分离。这是一种通过XML格式实现的UI描述,它可以通过Gtkuilder 类进行解析。

Example 4. Packing buttons with GtkBuilder

新建一个名为 example-4.c 的文件,写入如下内容:

  1. #include <gtk/gtk.h>
  2. static void print_hello (GtkWidget *widget,
  3. gpointer data)
  4. {
  5. g_print ("Hello World\n");
  6. }
  7. int main (int argc, char *argv[])
  8. {
  9. GtkBuilder *builder;
  10. GObject *window;
  11. GObject *button;
  12. gtk_init (&argc, &argv);
  13. /* Construct a GtkBuilder instance and load our UI description */
  14. builder = gtk_builder_new ();
  15. gtk_builder_add_from_file (builder, "builder.ui", NULL);
  16. /* Connect signal handlers to the constructed widgets. */
  17. window = gtk_builder_get_object (builder, "window");
  18. g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
  19. button = gtk_builder_get_object (builder, "button1");
  20. g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
  21. button = gtk_builder_get_object (builder, "button2");
  22. g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
  23. button = gtk_builder_get_object (builder, "quit");
  24. g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
  25. gtk_main ();
  26. return 0;
  27. }

新建一个名为builder.ui的文件,写入如下内容:

  1. <interface>
  2. <object id="window" class="GtkWindow">
  3. <property name="visible">True</property>
  4. <property name="title">Grid</property>
  5. <property name="border-width">10</property>
  6. <child>
  7. <object id="grid" class="GtkGrid">
  8. <property name="visible">True</property>
  9. <child>
  10. <object id="button1" class="GtkButton">
  11. <property name="visible">True</property>
  12. <property name="label">Button 1</property>
  13. </object>
  14. <packing>
  15. <property name="left-attach">0</property>
  16. <property name="top-attach">0</property>
  17. </packing>
  18. </child>
  19. <child>
  20. <object id="button2" class="GtkButton">
  21. <property name="visible">True</property>
  22. <property name="label">Button 2</property>
  23. </object>
  24. <packing>
  25. <property name="left-attach">1</property>
  26. <property name="top-attach">0</property>
  27. </packing>
  28. </child>
  29. <child>
  30. <object id="quit" class="GtkButton">
  31. <property name="visible">True</property>
  32. <property name="label">Quit</property>
  33. </object>
  34. <packing>
  35. <property name="left-attach">0</property>
  36. <property name="top-attach">1</property>
  37. <property name="width">2</property>
  38. </packing>
  39. </child>
  40. </object>
  41. <packing>
  42. </packing>
  43. </child>
  44. </object>
  45. </interface>

然后在终端输入以下命令用GCC编译程序:

  1. gcc `pkg-config --cflags gtk+-3.0` -o example-4 example-4.c `pkg-config --libs gtk+-3.0`

注意GtkBuilder也可以用来构建非控件的对象,例如树结构,调节器。这也是我们这里使用的方法叫做gtk_builder_get_object()并且返回值为GObject*而不是GtkWidget*的原因。
一般情况下,你将把一个完整路径传递给gtk_builder_add_from_file()使你的程序不依赖于当前路径运行。一个常用的放置UI描述和类似数据的目录是/usr/share/appname

也可以将UI描述以字符串的形式嵌入到源代码中,然后使用gtk_builder_add_from_string()加载。但是将UI描述放置在一个单独的文件有几个好处:首先,这让我们在对UI进行调整时不需要重新编译程序,而且,更重要的是,一些UI编辑器比如glade可以加载这种文件并且允许你通过点击就能够创建和修改你的UI。