Введение
В этом проекте мы создадим простое приложение секундомера с использованием библиотеки GTK на языке C. Этот секундомер будет иметь кнопку запуска/паузы и кнопку сброса для управления таймером секундомера. Мы разберем процесс на несколько этапов, начиная от настройки файлов проекта и заканчивая запуском приложения секундомера.
👀 Предпросмотр

🎯 Задачи
В этом проекте вы научитесь:
- Устанавливать библиотеку GTK
- Создавать файлы проекта
- Включать заголовочные файлы GTK и определять переменные
- Создавать функцию обратного вызова таймера
- Реализовывать обратные вызовы при нажатии кнопок
- Создавать главную функцию и элементы пользовательского интерфейса
- Компилировать и запускать проект
🏆 Достижения
После завершения этого проекта вы сможете:
- Использовать библиотеку GTK для создания графического пользовательского интерфейса на языке C
- Обрабатывать события нажатия кнопок в GTK
- Работать с таймерами в GTK
- Динамически обновлять метки в GTK
Создание файлов проекта
Сначала убедитесь, что на вашей системе установлена библиотека GTK. Если нет, вы можете использовать следующую команду для ее установки:
sudo apt update
sudo apt-get install libgtk-3-dev
Затем создайте новый файл с именем stopwatch.c и откройте его в вашем предпочитаемом текстовом редакторе кода.
cd ~/project
touch stopwatch.c
Подключение заголовочных файлов GTK и определение переменных
На этом этапе мы подключим необходимые заголовочные файлы GTK и определим переменные для нашего приложения секундомера.
#include <gtk/gtk.h>
static guint timer_id = 0;
static gboolean running = FALSE;
static int elapsed_seconds = 0;
static GtkWidget *label;
#include <gtk/gtk.h>: Этот заголовочный файл содержит объявления функций и структур данных библиотеки GTK, которые используются в программе.static guint timer_id = 0;: Это переменная, используемая для хранения идентификатора таймера GTK. Идентификатор таймера используется в следующем коде для управления запуском и остановкой таймера.static gboolean running = FALSE;: Это логическая переменная, которая отслеживает, запущен ли секундомер.runningравноTRUE, когда секундомер запущен, иFALSE, когда он приостановлен.static int elapsed_seconds = 0;: Это целочисленная переменная, которая отслеживает количество прошедших секунд. Она используется для вычисления прошедшего времени и отображения времени секундомера на метке.static GtkWidget *label;: Это указатель на виджет метки GTK. Эта метка отображает время секундомера.
Создание функции обратного вызова таймера
Далее мы создадим функцию обратного вызова, которая обновляет таймер секундомера каждую секунду.
static gboolean timer_callback(gpointer data) {
if (running) {
elapsed_seconds++;
int minutes = elapsed_seconds / 60;
int seconds = elapsed_seconds % 60;
char time_str[10];
snprintf(time_str, sizeof(time_str), "%02d:%02d", minutes, seconds);
gtk_label_set_text(GTK_LABEL(label), time_str);
}
return G_SOURCE_CONTINUE;
}
elapsed_seconds++: Если секундомер запущен, значение переменнойelapsed_secondsувеличивается, что означает, что количество прошедших секунд увеличилось на 1 секунду.- Поскольку одна минута равна 60 секундам, мы делим
elapsed_secondsна 60, чтобы получить количествоминут. Количествосекунд, меньшее одной минуты, можно получить с помощью оператора остатка от деления%. - Используем функцию
snprintfдля форматирования минут и секунд в строку в форматеmm:ss, где%02dозначает, что минуты и секунды должны быть представлены двумя цифрами, и если цифр меньше двух, то они дополняются ведущими нулями. gtk_label_set_textустанавливает только что сгенерированную строку времени в качестве текста метки, чтобы обновить отображение секундомера.return G_SOURCE_CONTINUEсообщает таймеру GTK продолжить работу после завершения обратного вызова, чтобы был снова вызван следующий событие таймера. Если обратный вызов возвращаетG_SOURCE_REMOVE, таймер останавливается.
В целом, функция timer_callback отвечает за динамическое обновление времени секундомера путем увеличения количества прошедших секунд, когда секундомер запущен, форматирования минут и секунд в строку и установки ее в качестве текста виджета метки.
Реализация функций обратного вызова для нажатий кнопок
Нам нужны функции обратного вызова для кнопок "Запуск/Пауза" и "Сброс".
static void start_stop_button_clicked(GtkButton *button, gpointer data) {
running =!running;
if (running) {
gtk_button_set_label(button, "Pause");
} else {
gtk_button_set_label(button, "Start");
}
}
static void reset_button_clicked(GtkButton *button, gpointer data) {
elapsed_seconds = 0;
gtk_label_set_text(GTK_LABEL(label), "00:00");
}
- Функция
start_stop_button_clickedпереключает состояние секундомера между запуском и паузой. - Функция
reset_button_clickedсбрасывает таймер секундомера.
Создание главной функции и элементов пользовательского интерфейса
Теперь создадим функцию main и настроим пользовательский интерфейс.
int main(int argc, char *argv[]) {
GtkWidget *window;
GtkWidget *grid;
GtkWidget *start_stop_button;
GtkWidget *reset_button;
gtk_init(&argc, &argv); // Инициализация GTK
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Stopwatch"); // Установка заголовка окна
gtk_window_set_default_size(GTK_WINDOW(window), 200, 200); // Установка размеров окна по умолчанию
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); // Подключение события закрытия окна
grid = gtk_grid_new(); // Создание сеточного макета
gtk_container_add(GTK_CONTAINER(window), grid); // Добавление сетки в окно
label = gtk_label_new("00:00"); // Создание метки GTK, изначально отображающей "00:00"
gtk_widget_set_hexpand(label, TRUE); // Разрешить метке расширяться по горизонтали
gtk_widget_set_vexpand(label, TRUE); // Разрешить метке расширяться по вертикали
gtk_grid_attach(GTK_GRID(grid), label, 0, 0, 1, 1); // Добавление метки в сетку
start_stop_button = gtk_button_new_with_label("Start"); // Создание кнопки с надписью "Start"
gtk_widget_set_hexpand(start_stop_button, TRUE); // Разрешить кнопке расширяться по горизонтали
gtk_widget_set_vexpand(start_stop_button, TRUE); // Разрешить кнопке расширяться по вертикали
g_signal_connect(G_OBJECT(start_stop_button), "clicked", G_CALLBACK(start_stop_button_clicked), NULL); // Подключение события нажатия кнопки
gtk_grid_attach(GTK_GRID(grid), start_stop_button, 0, 1, 1, 1); // Добавление кнопки в сетку
reset_button = gtk_button_new_with_label("Reset"); // Создание кнопки с надписью "Reset"
gtk_widget_set_hexpand(reset_button, TRUE); // Разрешить кнопке расширяться по горизонтали
gtk_widget_set_vexpand(reset_button, TRUE); // Разрешить кнопке расширяться по вертикали
g_signal_connect(G_OBJECT(reset_button), "clicked", G_CALLBACK(reset_button_clicked), NULL); // Подключение события нажатия кнопки
gtk_grid_attach(GTK_GRID(grid), reset_button, 0, 2, 1, 1); // Добавление кнопки в сетку
gtk_widget_show_all(window); // Отображение окна и всех его дочерних виджетов
timer_id = g_timeout_add(1000, timer_callback, NULL); // Создание таймера, срабатывающего каждые 1000 мс (1 секунда) и вызывающего timer_callback
gtk_main(); // Запуск главного цикла обработки событий GTK
return 0;
}
- Функция
mainнастраивает окно GTK, метки, кнопки и обработчики событий нажатия на них.
Компиляция и запуск проекта
Теперь, когда мы создали приложение секундомера, давайте скомпилируем и запустим его.
- Откройте терминал и перейдите в директорию проекта.
cd ~/project
- Скомпилируйте код с помощью следующей команды:
gcc -o stopwatch stopwatch.c $(pkg-config --cflags --libs gtk+-3.0)
- Запустите приложение:
./stopwatch
Вы должны увидеть окно с секундомером. Нажмите кнопку Start, чтобы запустить таймер, Pause, чтобы приостановить его, и Reset, чтобы сбросить таймер.

Резюме
В этом проекте мы создали простое приложение секундомера с использованием библиотеки GTK на языке C. Мы настроили файлы проекта, определили переменные, реализовали функцию обратного вызова таймера и создали обработчики событий нажатия кнопок. Приложение позволяет запускать, приостанавливать и сбрасывать таймер секундомера. Вы можете запустить его, скомпилировав код и выполнив полученную программу.



