Рис. 16.5
Как это работает
Вы добавили два новых элемента в программу gtk2.c: виджет GtkButtonи функцию обратного вызова. GtkButton— это виджет простой кнопки, которая может содержать текст, в нашем случае "Hello World", и порождает сигнал, названный clicked, каждый раз, когда кнопку щелкают мышью.
Функция обратного вызова button_clickedсвязана с сигналом clickedвиджета кнопки с помощью функции g_signal_connect:
g_signal_connect(GTK_OBJECT(app), "clicked",
GTK_SIGNAL_FUNC(button_clicked), "Button 1");
Обратите внимание на то, что имя кнопки — "Button 1" — передается в функцию обратного вызова как данные пользователя.
Весь остальной добавленный программный код касается виджета кнопки, создаваемой так же, как окно — вызовом функции gtk_button_new_with_label— функция gtk_widget_showделает ее видимой.
Для расположения кнопки в окне вызывается функция gtk_container_add. Эта простая функция помещает GtkWidgetвнутрь объекта GtkContainerи принимает контейнер и виджет как аргументы:
void gtk_container_add(GtkContainer* container, GtkWidget *widget);
Как вы уже знаете, GtkWindow— потомок или дочерний объект объекта GtkContainer. поэтому вы можете привести тип вашего объекта-окна к типу GtkContainerс помощью макроса GTK_CONTAINER:
gtk_container_add(GTK_CONTAINER(window), button);
Функция gtk_container_addпрекрасно подходит для расположения в окне одиночного виджета, но гораздо чаще вам потребуется для создания хорошего интерфейса размещать несколько виджетов в разных частях окна. У комплекта GTK+ есть специальные виджеты как раз для этой цели, именуемые виджетами упаковочных контейнеров,
Виджеты упаковочных контейнеров
Компоновка GUI исключительно важна для удобства применения интерфейса, и добиться наилучшей компоновки труднее всего. Реальная трудность в размещении виджетов заключается в том, что вы не можете полагаться на наличие у всех пользователей одинаковых размеров окон, тем, шрифтов и цветовых схем. То, что может быть отличным интерфейсом для одной системы, в другой системе может оказаться просто нечитаемым.
Для создания GUI, который выглядит одинаково во всех системах, вам необходимо избегать размещения виджетов на основе абсолютных координат и использовать более гибкую систему компоновки. У GTK+ есть для этой цели виджеты контейнеров. Виджеты-контейнеры позволяют управлять компоновкой виджетов в окнах вашего приложения. Виджеты упаковочных контейнеров (box) представляют очень удобный тип виджета-контейнера. GTK+ предлагает множество виджетов-контейнеров других типов, описанных в интерактивной документации к GTK+.
Виджеты упаковочных контейнеров — невидимые виджеты, задача которых — хранить другие виджеты и управлять их компоновкой или схемой размещения. Для управления размером отдельных виджетов, содержащихся в виджете упаковочного контейнера, вы задаете правила вместо координат. Поскольку виджеты упаковочных контейнеров могут содержать любые объекты GtkWidgetи объект GtkBoxсам является объектом типа GtkWidget, для создания сложных компоновок можно формировать виджеты упаковочных контейнеров, вложенные один в другой.
У типа GtkBoxсуществуют два основных подкласса:
□ GtkHBox— однострочный горизонтальный упаковочный контейнер;
□ GtkVBox— одностолбцовый вертикальный упаковочный контейнер.
После создания упаковочных контейнеров следует задать два параметра: homogeneousи spacing:
GtkWidget* gtk_hbox_new(gboolean homogeneous, gint spacing);
GtkWidget* gtk_vbox_new(gboolean homogeneous, gint spacing);
Эти параметры управляют компоновкой всех виджетов в конкретном упаковочном контейнере. Параметр homogeneous— логический, если он равен TRUE, виджеты занимают одинаковую площадь независимо от их индивидуальных размеров. Параметр spacingзадает расстояние между виджетами в пикселах.
После того как упаковочный контейнер создан, добавьте в него виджеты с помощью функций gtk_box_pack_startи gtk_box_pack_end:
void gtk_box_pack_start(GtkBox *box, GtkWidget *child,
gboolean expand, gboolean f ill, guint padding);
void gtk_box_pack_end(GtkBox *box, GtkWidget *child,
gboolean expand, gboolean fill, guint padding);
Функция gtk_box_pack_startвставляет виджеты, начиная от левого края контейнера GtkHBoxи нижнего края контейнера GtkVBox; функция gtk_box_pack_end, наоборот, начинает от правого и верхнего краев контейнера. Параметры функций управляют расстоянием между виджетами и форматом каждого виджета, находящегося в упаковочном контейнере.
Читать дальше