12. Глава 24: Настройка Виджетов и Стилизация
В этой главе мы подробно рассмотрим, как визуально настраивать элементы интерфейса (виджеты) в GTK. Это включает в себя изменение их размеров, цветов, шрифтов, а также управление общим поведением через свойства.
GTK предоставляет мощные механизмы для гибкого управления внешним видом и поведением виджетов: как программно, используя функции API, так и декларативно, через таблицы стилей CSS.
—
### Основные понятия и функции
`gtk_widget_set_size_request()`: Устанавливает минимальные требуемые размеры виджета (ширина, высота). Виджет не будет меньше этих размеров.
`gtk_widget_set_hexpand()`: Указывает, должен ли виджет расширяться по горизонтали, занимая доступное пространство. TRUE разрешает расширение.
`gtk_widget_set_vexpand()`: Указывает, должен ли виджет расширяться по вертикали, занимая доступное пространство. TRUE разрешает расширение.
`gtk_css_provider_new()`: Создает новый объект для загрузки CSS-стилей.
`gtk_css_provider_load_from_path()`: Загружает CSS-стили из указанного файла.
`gdk_screen_get_default()`: Получает объект GdkScreen, представляющий основной экран, к которому будут применены стили.
`gtk_style_context_add_provider_for_screen()`: Добавляет провайдер CSS-стилей для всего экрана, делая их глобально доступными.
`GTK_STYLE_PROVIDER_PRIORITY_USER`: Приоритет CSS-стилей, добавленных пользователем. Стиль пользователя переопределяет стиль темы.
`g_object_unref()`: Уменьшает счетчик ссылок на объект. Используется для освобождения ресурсов GtkCssProvider после его добавления.
`gtk_button_set_label()`: Устанавливает текстовую метку для GtkButton.
`gtk_label_set_justify()`: Устанавливает выравнивание текста внутри GtkLabel.
`gtk_entry_set_placeholder_text()`: Устанавливает текст-заполнитель (подсказку) для GtkEntry, который виден, когда поле пустое.
`gtk_entry_set_max_length()`: Устанавливает максимальное количество символов, которые можно ввести в GtkEntry.
`gtk_widget_set_sensitive()`: Делает виджет активным (TRUE) или неактивным (FALSE). Неактивные виджеты не реагируют на ввод пользователя.
`gtk_widget_set_visible()`: Делает виджет видимым (TRUE) или скрытым (FALSE).
`GtkCssProvider`_: Объект, который загружает и хранит CSS-стили.
`GtkStyleContext`_: Объект, через который виджеты получают и применяют стили.
`GdkScreen`_: Объект, представляющий экран дисплея.
—
### Исходные файлы в этой главе
В этой главе мы рассмотрим три практических примера:
- download:
file_chooser_open_example.c — Демонстрирует использование GtkFileChooserDialog для открытия существующего файла.
- download:
file_chooser_save_example.c — Показывает, как использовать GtkFileChooserDialog для сохранения нового файла или перезаписи существующего.
- download:
color_chooser_example.c — Иллюстрирует применение GtkColorChooserDialog для выбора цвета.
—
### Пример 24.1: Настройка Размеров Виджета и Гибкость Масштабирования
Файл: size_and_expand_example.c
В этом примере мы создадим окно с несколькими кнопками, чтобы наглядно показать, как gtk_widget_set_size_request() влияет на минимальный размер виджета, а gtk_widget_set_hexpand() и gtk_widget_set_vexpand() позволяют виджетам расширяться при изменении размеров окна.
#include <gtk/gtk.h>
/**
* @brief Главная функция программы.
* Демонстрирует настройку размеров и свойств расширения виджетов.
*
* @param argc Количество аргументов командной строки.
* @param argv Массив строк аргументов командной строки.
* @return Код завершения программы.
*/
int main(int argc, char *argv[]) {
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *button1, *button2, *button3;
gtk_init(&argc, &argv);
// 1. Создание главного окна
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Настройка Размеров и Расширения");
gtk_window_set_default_size(GTK_WINDOW(window), 400, 300); // Начальный размер окна
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
// 2. Создание GtkBox для размещения кнопок по вертикали
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); // Отступ между элементами 10px
gtk_container_set_border_width(GTK_CONTAINER(vbox), 10); // Внешний отступ 10px
gtk_container_add(GTK_CONTAINER(window), vbox);
// 3. Кнопка 1: Фиксированный размер
button1 = gtk_button_new_with_label("Фиксированный размер (150x50)");
// Устанавливаем минимальный требуемый размер виджета.
// Виджет никогда не будет меньше этих размеров, но может быть больше.
gtk_widget_set_size_request(button1, 150, 50);
// Не позволяем кнопке расширяться, она будет занимать только свой минимальный размер.
gtk_widget_set_hexpand(button1, FALSE);
gtk_widget_set_vexpand(button1, FALSE);
gtk_box_pack_start(GTK_BOX(vbox), button1, FALSE, FALSE, 0); // FALSE, FALSE - не расширять, не заполнять
// 4. Кнопка 2: Расширение по горизонтали
button2 = gtk_button_new_with_label("Расширение по горизонтали");
gtk_widget_set_size_request(button2, 100, 40); // Минимальный размер
gtk_widget_set_hexpand(button2, TRUE); // Позволяем кнопке расширяться по горизонтали
gtk_widget_set_vexpand(button2, FALSE); // Не позволяем расширяться по вертикали
gtk_box_pack_start(GTK_BOX(vbox), button2, TRUE, TRUE, 0); // TRUE, TRUE - расширять, заполнять
// 5. Кнопка 3: Расширение по вертикали
button3 = gtk_button_new_with_label("Расширение по вертикали");
gtk_widget_set_size_request(button3, 80, 60); // Минимальный размер
gtk_widget_set_hexpand(button3, FALSE); // Не позволяем расширяться по горизонтали
gtk_widget_set_vexpand(button3, TRUE); // Позволяем кнопке расширяться по вертикали
gtk_box_pack_start(GTK_BOX(vbox), button3, TRUE, TRUE, 0); // TRUE, TRUE - расширять, заполнять
// 6. Отображение всех виджетов и запуск главного цикла GTK
gtk_widget_show_all(window);
gtk_main();
return 0;
}
—
### Пример 24.2: Настройка Шрифтов и Цветов через CSS
Файл: css_styling_example.c
Этот пример покажет, как использовать CSS-файл для стилизации виджетов GTK. Мы создадим окно с кнопкой и меткой, а затем применим к ним стили из внешнего файла style.css, чтобы изменить шрифт, цвет текста и фон.
Создайте файл ``style.css`` в той же директории:
/* style.css */
/* Стиль для всех кнопок */
button {
font-size: 18px; /* Размер шрифта */
font-weight: bold; /* Жирный шрифт */
color: white; /* Цвет текста */
background-color: #3f51b5; /* Темно-синий фон */
border-radius: 8px; /* Скругление углов */
padding: 10px 20px; /* Внутренние отступы */
border: 2px solid #283593; /* Рамка */
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3); /* Тень */
}
/* Стиль при наведении на кнопку */
button:hover {
background-color: #5c6bc0; /* Более светлый синий */
}
/* Стиль при нажатии кнопки */
button:active {
background-color: #303f9f; /* Темнее синий */
box-shadow: inset 1px 1px 3px rgba(0, 0, 0, 0.4); /* Внутренняя тень */
}
/* Стиль для GtkLabel */
label {
font-family: "Monospace"; /* Моноширинный шрифт */
font-size: 20px; /* Размер шрифта */
color: #e91e63; /* Ярко-розовый цвет текста */
margin-bottom: 20px; /* Отступ снизу */
}
Исходный код ``css_styling_example.c``:
#include <gtk/gtk.h>
/**
* @brief Загружает и применяет CSS-стили из файла.
*
* @param css_file_path Путь к CSS-файлу.
*/
static void load_css(const char *css_file_path) {
GtkCssProvider *provider = gtk_css_provider_new(); // Создаем