Глава 18: Элементы Пользовательского Ввода ========================================== В этой главе мы сосредоточимся на ключевых элементах пользовательского ввода в GTK, которые позволяют вашему приложению получать информацию от пользователя. Мы рассмотрим три основных виджета: * :doc: `GtkEntry ` — **однострочное текстовое поле** для ввода текста. * :doc: `GtkSpinButton ` — **числовой спиннер** для ввода чисел в заданном диапазоне. * :doc: `GtkCheckButton ` — **чекбокс (флажок)** для переключения логических состояний (включено/выключено). Эти виджеты являются основой для создания интерактивных форм, настроек и других элементов управления, где требуется получить данные от пользователя. --- GtkEntry: Однострочное Текстовое Поле -------------------------------------- `GtkEntry` — это универсальный виджет для ввода и отображения однострочного текста. Он широко используется для полей ввода имени пользователя, пароля, пути к файлу, поисковых запросов и других текстовых данных. ### Основные функции и свойства GtkEntry: * ``gtk_entry_new()``: Создаёт новый пустой `GtkEntry`. * ``gtk_entry_new_with_buffer(GtkEntryBuffer *buffer)``: Создаёт `GtkEntry` с привязанным буфером, что даёт больше контроля над текстом. * ``gtk_entry_set_text(GtkEntry *entry, const gchar *text)``: Устанавливает текст в поле ввода. * ``gtk_entry_get_text(GtkEntry *entry)``: Получает текущий текст из поля ввода. Возвращаемая строка принадлежит виджету, её не нужно освобождать, но она станет недействительной после изменения текста. * ``gtk_entry_set_visibility(GtkEntry *entry, gboolean visible)``: Управляет видимостью текста (например, для полей пароля). `FALSE` скрывает текст, отображая символы-заполнители. * ``gtk_entry_set_placeholder_text(GtkEntry *entry, const gchar *text)``: Устанавливает текст-подсказку, который отображается, когда поле пустое и не в фокусе. ### Сигналы GtkEntry: * ``"changed"``: Испускается при любом изменении текста в поле ввода. * ``"activate"``: Испускается, когда пользователь нажимает Enter в поле ввода (часто используется для подтверждения ввода). --- GtkSpinButton: Числовой Спиннер -------------------------------- `GtkSpinButton` — это удобный виджет для ввода числовых значений в определённом диапазоне. Он состоит из текстового поля и двух кнопок (стрелок) для увеличения или уменьшения значения. Идеально подходит для ввода количества, уровня громкости, выбора номера страницы и т.д. `GtkSpinButton` тесно связан с объектом `GtkAdjustment`, который определяет диапазон значений, шаг изменения и текущее значение. ### Основные функции GtkSpinButton: * ``gtk_adjustment_new(gdouble value, gdouble lower, gdouble upper, gdouble step_increment, gdouble page_increment, gdouble page_size)``: Создаёт новый объект `GtkAdjustment`. * ``value``: Начальное значение. * ``lower``: Минимально допустимое значение. * ``upper``: Максимально допустимое значение. * ``step_increment``: Шаг изменения при нажатии на стрелки (один щелчок). * ``page_increment``: Шаг изменения при нажатии PageUp/PageDown (или Shift+стрелки). * ``page_size``: Обычно 0 для `GtkSpinButton`. * ``gtk_spin_button_new(GtkAdjustment *adjustment, gdouble climb_rate, guint digits)``: Создаёт новый `GtkSpinButton`. * ``adjustment``: Объект `GtkAdjustment`, управляющий значениями. * ``climb_rate``: Коэффициент ускорения изменения значения при удержании кнопки (обычно 1.0). * ``digits``: Количество знаков после запятой для отображения. 0 для целых чисел. * ``gtk_spin_button_get_value_as_int(GtkSpinButton *spin_button)``: Получает текущее значение спиннера как целое число. * ``gtk_spin_button_get_value(GtkSpinButton *spin_button)``: Получает текущее значение спиннера как `gdouble`. * ``gtk_spin_button_set_value(GtkSpinButton *spin_button, gdouble value)``: Устанавливает значение спиннера. ### Сигналы GtkSpinButton: * ``"value-changed"``: Испускается при любом изменении значения в спиннере (как от стрелок, так и от ручного ввода). --- GtkCheckButton: Флажок (Чекбокс) --------------------------------- `GtkCheckButton` — это простой виджет-переключатель, который имеет два состояния: отмечен (включен) или не отмечен (выключен). Он используется для представления логических опций, которые пользователь может включить или выключить. ### Основные функции GtkCheckButton: * ``gtk_check_button_new()``: Создаёт новый пустой `GtkCheckButton`. * ``gtk_check_button_new_with_label(const gchar *label)``: Создаёт `GtkCheckButton` с текстовой меткой рядом. * ``gtk_check_button_new_with_mnemonic(const gchar *label)``: Создаёт `GtkCheckButton` с меткой, где подчёркнутый символ может быть использован для активации с клавиатуры (акселератор). * ``gtk_toggle_button_get_active(GtkToggleButton *button)``: Получает текущее состояние чекбокса (`TRUE` если отмечен, `FALSE` если нет). `GtkCheckButton` является наследником `GtkToggleButton`. * ``gtk_toggle_button_set_active(GtkToggleButton *button, gboolean is_active)``: Устанавливает состояние чекбокса программно. ### Сигналы GtkCheckButton: * ``"toggled"``: Испускается каждый раз, когда состояние чекбокса меняется (пользователь отмечает или снимает отметку). --- Обработка Событий: Общие Принципы ---------------------------------- Для всех этих виджетов, как и для `GtkButton`, основным механизмом взаимодействия является система **сигналов и слотов (callbacks)**. Вы подключаете (``g_signal_connect``) свои функции-обработчики (``callbacks``) к определённым сигналам, которые испускают виджеты при определённых действиях пользователя. Пример подключения сигналов: .. code-block:: c g_signal_connect(entry, "changed", G_CALLBACK(on_entry_changed), NULL); g_signal_connect(spin, "value-changed", G_CALLBACK(on_spin_changed), NULL); g_signal_connect(check, "toggled", G_CALLBACK(on_check_toggled), NULL); --- ### Пример 18.1: Окно с текстовым полем, спиннером и чекбоксом Название исходного файла: `input_widgets_example.c` Эта программа демонстрирует создание окна с тремя описанными выше элементами ввода. Все они размещены вертикально с помощью `GtkBox`, а их изменения отслеживаются через соответствующие callback-функции, выводящие информацию в консоль. .. code-block:: c #include // Подключаем основную библиотеку GTK. /** * @brief Обработчик сигнала "changed" для GtkEntry. * Вызывается каждый раз при изменении текста в GtkEntry. * @param entry Указатель на GtkEntry, который испустил сигнал. * @param user_data Пользовательские данные (в данном случае NULL). */ void on_entry_changed(GtkEntry *entry, gpointer user_data) { // Получаем текущий текст из поля ввода. const gchar *text = gtk_entry_get_text(entry); g_print("Entry changed: %s\n", text); } /** * @brief Обработчик сигнала "value-changed" для GtkSpinButton. * Вызывается каждый раз при изменении числового значения в GtkSpinButton. * @param spin Указатель на GtkSpinButton, который испустил сигнал. * @param user_data Пользовательские данные (в данном случае NULL). */ void on_spin_changed(GtkSpinButton *spin, gpointer user_data) { // Получаем текущее значение спиннера как целое число. gint value = gtk_spin_button_get_value_as_int(spin); g_print("Spin value: %d\n", value); } /** * @brief Обработчик сигнала "toggled" для GtkCheckButton. * Вызывается каждый раз при изменении состояния чекбокса (отмечен/не отмечен). * @param check Указатель на GtkToggleButton (базовый класс для GtkCheckButton), * который испустил сигнал. * @param user_data Пользовательские данные (в данном случае NULL). */ void on_check_toggled(GtkToggleButton *check, gpointer user_data) { // Проверяем, активно ли (отмечено) состояние чекбокса. gboolean active = gtk_toggle_button_get_active(check); g_print("Check toggled: %s\n", active ? "ON" : "OFF"); // Выводим "ON" или "OFF" } /** * @brief Главная функция программы, точка входа. * Инициализирует GTK, создает окно, добавляет в него элементы ввода * и запускает главный цикл событий GTK. * @param argc Количество аргументов командной строки. * @param argv Массив строк аргументов командной строки. * @return Код завершения программы. */ int main(int argc, char *argv[]) { // Инициализация GTK. Всегда вызывается первой. gtk_init(&argc, &argv); // 1. Создание главного окна приложения. GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "Пример Полей Ввода"); gtk_window_set_default_size(GTK_WINDOW(window), 300, 200); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); // Подключение сигнала "destroy" для корректного завершения приложения. g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); // 2. Создание вертикального контейнера GtkBox. // Используем GtkBox для размещения всех виджетов вертикально, // с отступом в 10 пикселей между ними. GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); // Добавляем GtkBox в главное окно. gtk_container_add(GTK_CONTAINER(window), vbox); // 3. Создание GtkEntry (текстового поля). GtkWidget *entry = gtk_entry_new(); // Устанавливаем текст-заполнитель, который виден, когда поле пустое. gtk_entry_set_placeholder_text(GTK_ENTRY(entry), "Введите ваше имя..."); // Добавляем GtkEntry в вертикальный GtkBox. gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0); // Подключаем обработчик на изменение текста. g_signal_connect(entry, "changed", G_CALLBACK(on_entry_changed), NULL); // 4. Создание GtkSpinButton (числового спиннера). // Сначала создаем объект GtkAdjustment, который определяет диапазон и шаг. // (начальное значение, нижний предел, верхний предел, шаг при клике, шаг при PageUp/Down, размер страницы) GtkAdjustment *adj = gtk_adjustment_new(0, 0, 100, 1, 10, 0); // Создаем спиннер, привязывая его к созданному GtkAdjustment. // 1.0 - скорость "взбирания" при удержании кнопки, 0 - количество знаков после запятой (целые числа). GtkWidget *spin = gtk_spin_button_new(adj, 1.0, 0); // Добавляем спиннер в вертикальный GtkBox. gtk_box_pack_start(GTK_BOX(vbox), spin, FALSE, FALSE, 0); // Подключаем обработчик на изменение значения. g_signal_connect(spin, "value-changed", G_CALLBACK(on_spin_changed), NULL); // 5. Создание GtkCheckButton (флажка/чекбокса). GtkWidget *check = gtk_check_button_new_with_label("Я согласен с условиями"); // Устанавливаем начальное состояние чекбокса (например, изначально не отмечен). gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE); // Добавляем чекбокс в вертикальный GtkBox. gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); // Подключаем обработчик на изменение состояния. g_signal_connect(check, "toggled", G_CALLBACK(on_check_toggled), NULL); // 6. Отображение всех виджетов в окне. gtk_widget_show_all(window); // 7. Запуск главного цикла событий GTK. // Приложение будет ждать действий пользователя, пока не будет закрыто. gtk_main(); return 0; // Возвращаем код успешного завершения. } --- Компиляция и Запуск -------------------- Сохраните код выше в файл с именем `input_widgets_example.c`. ### Компиляция: Для сборки программы используйте следующую команду в терминале, находясь в директории с исходным файлом: .. code-block:: bash gcc input_widgets_example.c -o input_widgets_example `pkg-config --cflags --libs gtk+-3.0` ### Запуск: После успешной компиляции вы можете запустить ваше приложение: .. code-block:: bash ./input_widgets_example --- Ожидаемый результат ------------------- При запуске программы вы увидите окно с заголовком "Пример Полей Ввода". Внутри окна будут расположены вертикально следующие элементы: * **Текстовое поле (`GtkEntry`)**: Будет отображаться текст-подсказка "Введите ваше имя...". При вводе текста, каждое изменение символа будет выводиться в консоль. * **Числовой спиннер (`GtkSpinButton`)**: Будет показывать числовое значение (изначально 0), которое можно изменять с помощью стрелок вверх/вниз или вводя число вручную. Каждое изменение значения будет выводиться в консоль. * **Чекбокс (`GtkCheckButton`)**: Рядом с ним будет метка "Я согласен с условиями". Изначально чекбокс будет не отмечен. При клике на него, его состояние будет меняться между "ON" и "OFF", и это изменение будет выводиться в консоль. --- Дополнительные материалы ------------------------- * `GtkEntry`_: Официальная документация GtkEntry. * `GtkSpinButton`_: Официальная документация GtkSpinButton. * `GtkCheckButton`_: Официальная документация GtkCheckButton. * `GtkAdjustment`_: Официальная документация GtkAdjustment. * `C_GUI_Handbook GitHub`_ - Репозиторий с примерами кода из этого руководства. --- Навигация --------- * :doc: `Глава 17: Гибкая Компоновка с GtkGrid ` * :doc: `Глава 19: Выпадающие списки и радиокнопки ` .. _GtkEntry: https://docs.gtk.org/gtk3/class.Entry.html .. _GtkSpinButton: https://docs.gtk.org/gtk3/class.SpinButton.html .. _GtkCheckButton: https://docs.gtk.org/gtk3/class.CheckButton.html .. _GtkAdjustment: https://docs.gtk.org/gtk3/class.Adjustment.html .. _C_GUI_Handbook GitHub: https://github.com/AIDevelopersMonster/C_GUI_Handbook