Как мы узнали из вступления, каждый визуальный элемент (виджет, или контрол) имеет свою иерархию, напоминающую DOM-дерево HTML. Для построения интерфейса, мы должны научиться комбинировать такие виджеты, и понимать как они управляются.
Итак, виджеты. Их сотни. Однако на данном этапе для построения интерфейса 50% программ, мы изучим всего восемь. Вот они:
GtkBox. Блочный, «невидимый» виджет, который является контейнером, то есть способен размещать в себе другие виджеты, и сам быть размещенным в других. Аналог <div> из мира HTML.
GtkLabel. Строка. Просто текстовая строка.
GtkButton. Кнопка, которую можно нажимать и обрабатывать это нажатие. Может вмещать в себя как картинку, так и текст. Тоже является контейнером, т.е. может содержать другие элементы, однако в отличие от GtkBox, способно обрабатывать на себе специфические сигналы (об этом в следующих уроках).
GtkImage. Картинка, из разных ресурсов: файла, имени иконки, буфера пикселей, которую можно вывести в окне как изображение.
GtkScrolledWindow. Тоже блочный виджет, практически аналог GtkBox, только с полосами прокрутки, вызываемыми согласно правилам.
Теперь детальнее на примерах.
#!/usr/local/supreme/php/bin/php
<?php
Gtk::init();
function GtkWindowDestroy($widget=NULL, $event=NULL)
{
Gtk::main_quit();
}
$win = new GtkWindow();
$win->set_default_size(640, 480);
$win->connect("destroy", "GtkWindowDestroy");
$box = new GtkBox(GtkOrientation::HORIZONTAL, 5);
$label_1 = new GtkLabel("Hello");
$label_2 = new GtkLabel("World");
$box->add($label_1);
$box->add($label_2);
$win->add($box);
$win->show_all();
Gtk::main();
Обратите внимание на последовательность встраивания виджетов. Сначала мы встроили наши $label_1 и $label_2 в $box, и лишь затем встроили $box в $win.
Наверняка вы обратили внимание на параметры в скобках GtkBox. Их два, и они просты. Первый параметр — это константа, определяющая расположение дочерних элементов в контейнере. Таких параметров тоже всего два: GtkOrientation::HORIZONTAL и GtkOrientation::VERTICAL. При горизонтальном расположении, последний элемент добавленный в бокс будет располагаться справа от предыдущего (справа налево), при вертикальном — снизу (сверху вниз).
Второй параметр — это отступ в пикселях между элементами в боксе.
Давайте попробуем.
#!/usr/local/supreme/php/bin/php
<?php
Gtk::init();
function GtkWindowDestroy($widget=NULL, $event=NULL)
{
Gtk::main_quit();
}
$win = new GtkWindow();
$win->set_default_size(640, 480);
$win->connect("destroy", "GtkWindowDestroy");
$box = new GtkBox(GtkOrientation::VERTICAL, 20);
$label_1 = new GtkLabel("Hello");
$label_2 = new GtkLabel("World");
$box->add($label_1);
$box->add($label_2);
$win->add($box);
$win->show_all();
Gtk::main();

Почти все виджеты GTK имеют свойства, устанавливаемые специальными функциями. Большинство из этих функций одинаково для всех виджетов, некоторые функции контейнероспецифичны, т.е. влияют на параметры только виджетов-контейнеров, и только малая часть виджетоспецифичны, т.е. применяются только к конкретным виджетам.
Перечислим несколько функций, которые можно применить к GtkBox.
set_homogeneous(bool). Этот параметр устанавливает одинаковую ширину или высоту для всех объектов в контейнере. Рассмотрим пример, но без кода:
Допустим у нас есть две кнопки, с надписями «Test» и «Click me please«. Пусть размер шрифта у нас будет 8 пикселей. Тогда длина первой кнопки будет 32 пикселя, а длина второй 120 пикселей. Однако, если если установить родительскому контейнеру этих кнопок set_homogeneous в true — обе кнопки будут одинаковой длины в 120 пикселей (по размеру самой большой).
Эта функция действует только для виджетов контейнерного типа.
set_hexpand(bool) и set_vexpand(bool). Эти интересные функции позволяют виджету автоматически расширяться, если есть куда. Например заполнять все пространство окна при его расширении. Функции работают для любых виджетов.
set_size_request(int width, int height). Так мы принудительно устанавливаем размер виджета. В принципе это применимо к любым виджетам, однако стоит учесть, что работать это будет только с тем что способно масштабироваться в системе координат. Размер шрифта так не увеличить.
Кстати, если мы хотим изменить размер только одной стороны, оставив другую как есть — мы можем просто поставить -1 (минус один) для той части, которую не хотим изменять.
set_halign(int GtkAlign) и set_valign(int GtkAlign). Этими функциями мы выравниваем элемент относительно виджета, в котором этот элемент расположен. Здесь лучше использовать числовое значение, взятое из официальной документации GTK: https://docs.gtk.org/gtk3/enum.Align.html
Выравнивание в GTK специфическое, здесь нет левой и правой части, а вместо них есть начальная, конечная, центральная, и заполняемая. Соответственно если нам по вертикали нужно разместить виджет внизу, то мы выбираем GTK_ALIGN_END (число 2, согласно документации), поскольку в нашей классической системе координат, отрисовка идет сверху вниз — сверху START, снизу END.
Поехали дальше, GtkLabel(string $text).
В принципе, как работает этот виджет — мы уже увидели в предыдущем примере.
Особо интересных функций у этого виджета мало, мы упомянем лишь две
set_text(string $text) — изменяет текст у уже существующей GtkLabel.
set_user_markup(bool) — позволяет использовать некоторую разметку в самом тексте, по принципу тегов HTML.