• 构建用户界面

    构建用户界面

    当我们构建一个更加复杂的带有成百控件的用户界面时,用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。