Создание пользовательских интерфейсов
При создании более сложных пользовательских интерфейсов, содержащих десятки или сотни виджетов, выполнение всей работы по настройке на C затруднительно, а внесение изменений становится практически невозможным.
К счастью, GTK+ поддерживает разделение макета пользовательского интерфейса и бизнес-логики с помощью описаний интерфейса в формате XML, которые могут быть обработаны классом GtkBuilder.
Пример 3. Размещение кнопок с помощью GtkBuilder
Создайте новый файл с именем example-3.c, содержащий следующий код.
#include <gtk/gtk.h>
static void
print_hello (GtkWidget *widget,
gpointer data)
{
g_print ("Hello World\n");
}
int
main (int argc,
char *argv[])
{
GtkBuilder *builder;
GObject *window;
GObject *button;
GError *error = NULL;
gtk_init (&argc, &argv);
/* Construct a GtkBuilder instance and load our UI description */
builder = gtk_builder_new ();
if (gtk_builder_add_from_file (builder, "builder.ui", &error) == 0)
{
g_printerr ("Error loading file: %s\n", error->message);
g_clear_error (&error);
return 1;
}
/* Connect signal handlers to the constructed widgets. */
window = gtk_builder_get_object (builder, "window");
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
button = gtk_builder_get_object (builder, "button1");
g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
button = gtk_builder_get_object (builder, "button2");
g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
button = gtk_builder_get_object (builder, "quit");
g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
gtk_main ();
return 0;
}
Создайте новый файл с именем builder.ui, содержащий следующий код.
<interface>
<object id="window" class="GtkWindow">
<property name="visible">True</property>
<property name="title">Grid</property>
<property name="border-width">10</property>
<child>
<object id="grid" class="GtkGrid">
<property name="visible">True</property>
<child>
<object id="button1" class="GtkButton">
<property name="visible">True</property>
<property name="label">Button 1</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object id="button2" class="GtkButton">
<property name="visible">True</property>
<property name="label">Button 2</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object id="quit" class="GtkButton">
<property name="visible">True</property>
<property name="label">Quit</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
<property name="width">2</property>
</packing>
</child>
</object>
<packing>
</packing>
</child>
</object>
</interface>
Вы можете скомпилировать программу выше с помощью GCC, используя следующую команду:
gcc `pkg-config --cflags gtk+-3.0` -o example-3 example-3.c `pkg-config --libs gtk+-3.0`
Обратите внимание, что GtkBuilder также может использоваться для создания объектов, которые не являются виджетами, таких как модели деревьев, настройки и т. д. Поэтому метод, который мы используем здесь, называется gtk_builder_get_object() и возвращает GObject* вместо GtkWidget*.
Обычно вы передаете полный путь к gtk_builder_add_from_file(), чтобы сделать выполнение программы независимым от текущей директории. Общее место для установки описаний интерфейса и подобных данных — /usr/share/. appname
Также можно встроить описание интерфейса в исходный код в виде строки и использовать gtk_builder_add_from_string() для его загрузки. Однако хранение описания интерфейса в отдельном файле имеет несколько преимуществ: это позволяет вносить незначительные изменения в интерфейс без перекомпиляции программы, и, что более важно, графические редакторы интерфейсов, такие как glade, могут загрузить этот файл и позволить вам создавать и изменять интерфейс с помощью перетаскивания.
© 2005–2020 The GNOME Project
Licensed under the GNU Lesser General Public License version 2.1 or later.
https://developer.gnome.org/gtk3/3.24/ch01s03.html