Глава 15: Кнопки и обработка событий ==================================== В этой главе мы углубимся в работу с одним из самых фундаментальных элементов графического интерфейса — **кнопками**. Мы научимся создавать кнопки с текстом, размещать их в окне и, самое главное, обрабатывать **пользовательские действия**, такие как клики мышью. Это важный шаг в освоении **событийно-ориентированного программирования** с использованием библиотеки GTK, которое является краеугольным камнем любого интерактивного приложения. Что вы узнаете в этой главе: ---------------------------- * **Как создать базовую кнопку** с текстовой меткой. * **Что такое "сигналы" в GTK** и как они являются основой обработки событий. * **Как "подключить" (connect) ваш код** к сигналам, испускаемым виджетами. * **Как написать функцию-обработчик** (callback) для реакции на клик по кнопке. * **Как использовать `g_print()`** для вывода отладочной информации. --- ### Основы взаимодействия: Сигналы и Слоты Как мы уже кратко упоминали в предыдущих главах, GTK использует **событийно-ориентированную модель**. Это означает, что программа не выполняет команды строго по порядку, а реагирует на "события", происходящие в интерфейсе. Ядро этой модели в GTK — это система **"сигналов и слотов" (signals and slots)**, реализованная через **GObject**. * **Сигнал (Signal):** Это уведомление, которое "испускает" виджет (или любой другой GObject) в ответ на определённое событие. Например, когда пользователь нажимает на кнопку, кнопка испускает сигнал "clicked". Когда окно закрывается, оно испускает сигнал "destroy". * **Слот (Slot) / Обработчик события (Callback Function):** Это обычная функция на языке C, которую вы пишете. Вы "подключаете" эту функцию к определённому сигналу определённого виджета. Когда виджет испускает сигнал, GTK автоматически вызывает (или "активирует") все подключенные к этому сигналу функции-обработчики. Механизм ``g_signal_connect()``, который мы использовали ранее для закрытия окна, является центральным для этой системы. Он позволяет установить связь между сигналом, исходящим от виджета, и вашей функцией, которая должна быть вызвана в ответ. --- ### Пример: Простое окно с кнопкой и выводом в консоль Название исходного файла: `button_example.c` Этот пример покажет, как создать окно с одной кнопкой. При каждом нажатии на кнопку в терминале будет появляться сообщение. .. code-block:: c #include // Подключаем основную библиотеку GTK. /** * @brief Callback-функция, которая будет вызвана при нажатии кнопки. * * Эта функция просто выводит сообщение в консоль, демонстрируя, * что сигнал "clicked" был успешно обработан. * * @param widget Указатель на GtkWidget, который испустил сигнал (в данном случае, GtkButton). * Хотя мы не используем его явно в этой функции, он всегда передаётся. * @param data Универсальный указатель на пользовательские данные. * В этом примере мы передаём NULL, так как никаких дополнительных данных не требуется. */ static void on_button_clicked(GtkWidget *widget, gpointer data) { // g_print() - это функция из библиотеки GLib (основа GTK), // аналогичная printf(), но с лучшей поддержкой для вывода в консоль // в GUI-приложениях GTK (особенно при запуске из IDE или без прямого терминала). g_print("Кнопка 'Нажми меня' была нажата!\n"); } /** * @brief Главная функция программы, точка входа. * * Инициализирует GTK, создаёт главное окно, кнопку, * подключает обработчики событий и запускает основной цикл GTK. * * @param argc Количество аргументов командной строки. * @param argv Массив строк аргументов командной строки. * @return Код завершения программы (0 при успешном выполнении). */ int main(int argc, char *argv[]) { // 1. Инициализация GTK. // Это обязательный первый вызов в любой GTK-программе. Он подготавливает // библиотеку, обрабатывает специфические аргументы командной строки GTK. gtk_init(&argc, &argv); // 2. Создание главного окна. // Создаётся новое окно верхнего уровня. GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); // 3. Настройка окна. // Устанавливаем заголовок окна. 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); // 4. Подключение сигнала закрытия окна. // Когда пользователь закрывает окно (например, через кнопку "X"), // испускается сигнал "destroy". Мы подключаем его к gtk_main_quit(), // чтобы корректно завершить главный цикл GTK и, как следствие, программу. g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); // 5. Создание кнопки. // Создаём новую кнопку с текстовой меткой. GtkWidget *button = gtk_button_new_with_label("Нажми меня"); // 6. Подключение обработчика к сигналу кнопки. // Подключаем сигнал "clicked" от нашей кнопки к функции on_button_clicked. // Когда кнопка будет нажата, вызовется наша функция. // Здесь мы передаём NULL в качестве пользовательских данных, // так как on_button_clicked не требует никаких дополнительных данных. g_signal_connect(button, "clicked", G_CALLBACK(on_button_clicked), NULL); // 7. Добавление кнопки в окно. // Добавляем созданную кнопку в окно. В GTK3 окна могут содержать // только один прямой дочерний виджет. gtk_container_add(GTK_CONTAINER(window), button); // 8. Отображение всех виджетов. // Все виджеты GTK по умолчанию невидимы. Эта функция делает окно // и все его дочерние элементы (в данном случае, кнопку) видимыми. gtk_widget_show_all(window); // 9. Запуск главного цикла событий GTK. // Эта функция передаёт управление GTK. Программа будет ждать // и обрабатывать события до тех пор, пока gtk_main_quit() не будет вызвана. gtk_main(); // 10. Завершение программы. // Код возврата 0 указывает на успешное выполнение. return 0; } --- ### Компиляция и Запуск Сохраните код выше в файл с именем `button_example.c`. **Компиляция:** Для сборки программы на Raspberry Pi (или любой другой системе с GTK3) используйте следующую команду в терминале, находясь в директории с исходным файлом: .. code-block:: bash gcc -o button_example button_example.c `pkg-config --cflags --libs gtk+-3.0` * ``gcc -o button_example button_example.c``: Указывает компилятору GCC взять исходный файл ``button_example.c`` и создать исполняемый файл с именем ``button_example``. * `` `pkg-config --cflags --libs gtk+-3.0` ``: Это очень важная часть. Утилита ``pkg-config`` автоматически предоставляет GCC все необходимые пути к заголовочным файлам (``--cflags``) и библиотекам (``--libs``), которые требуются для успешной компиляции GTK3-приложения. **Запуск:** После успешной компиляции вы можете запустить ваше приложение: .. code-block:: bash ./button_example --- ### Ожидаемый результат * На вашем рабочем столе появится новое окно с заголовком "Пример кнопки". * В центре этого окна будет расположена кнопка с надписью **«Нажми меня»**. * При каждом нажатии на эту кнопку в терминале, из которого вы запустили программу, будет появляться строка: :: Кнопка 'Нажми меня' была нажата! * Вы можете закрыть окно, нажав на кнопку "X" в заголовке окна или используя комбинацию клавиш (например, Alt+F4), что приведёт к корректному завершению программы. ---