Поставим для
себя задачу реализовать программу,
которая будет представлять из себя
главное окно с кнопкой. По нажатию на
кнопку она перемещается в новую позицию,
если кнопка нажата из новой позиции,
то кнопка возвращается на свое исходное
место.
Разобьем наши
дальнейшие действия:
1) Создадим
главное окно. Здесь все как обычно,
подключаем заголовочный файл gtk:
#include <gtk/gtk.h>
Потом создадим
главную функцию программы:
int main(int argc, char
**argv) {
return 0;
}
В теле главной
функции определим указатель на главное
окно:
GtkWidget *window;
Проведем
инициализацию gtk:
gtk_init(&argc,
&argv);
Создадим окно:
window = gtk_window_new
(GTK_WINDOW_TOPLEVEL);
Присвоим заголовок
окну:
gtk_window_set_title
(GTK_WINDOW (window), "Gtk_p5");
Разместим в
центре рабочего стола:
gtk_window_set_position(GTK_WINDOW(window),
GTK_WIN_POS_CENTER);
Установим размер
окна:
gtk_window_set_default_size(GTK_WINDOW(window),
200, 200);
Установим границу
окна:
gtk_container_set_border_width
(GTK_CONTAINER (window), 10);
Установим сигнал
закрытия окна:
g_signal_connect(window,
"destroy", G_CALLBACK(gtk_main_quit), NULL);
Отобразим все
виджеты окна:
gtk_widget_show_all(window);
Передадим
управление библиотеки GTK:
gtk_main();
Необходимый
минимум для создания главного окна мы
рассмотрели. Пойдем дальше и добавим
кнопку.
Чтобы добавить
кнопку в окно, мы должны создать контейнер
и разместить его в главном окне. Для
позиционирования элементов управления
в определенных координатах существует
контейнер GtkFixed.
Объявим указатель
на наш будущий контейнер, его нужно
разместить в начале главной функции
программы, напишем следующую строчку
кода:
GtkWidget *fixed;
после строчки
GtkWidget *button;
а указатель на
кнопку после объявления указателя на
главное окно:
GtkWidget *window;
Далее определим
массив указателей который мы передадим
в функцию обработки нажатия на виджет
кнопки.
gpointer data[3];
Теперь ниже, там
где мы подключили Gtk заголовочный файл
#include <gtk/gtk.h>, объявим две структуры:
1) Одна структура
описывает размер кнопки
struct button_size {
gint width;
gint height;
};
2) Вторая структура
описывает позицию кнопки
struct button_position
{
gint x;
gint y;
};
После объявления
структур, ниже объявим булеву переменную
которая будет «переключать» положение
кнопки:
gboolean
f_switch = FALSE;
В главной функции
программы, там где мы объявили массив
указателей
gpointer data[3];
ниже мы должный
объявить переменную на структуру с
именем button_size и две переменные на
структуру с именем button_position и присвоить
всем этим структурам значения:
struct button_size bs =
{ 80, 35 };
struct button_position
bp1 = { 55, 10 };
struct button_position
bp2 = { 55, 135 };
Ниже, после этих
строчек, объявим два указателя на
структуру типа button_position:
struct button_position
*p_bp1;
struct button_position
*p_bp2;
Теперь давайте
создадим контейнер, после строчки:
g_signal_connect(window,
"destroy", G_CALLBACK(gtk_main_quit), NULL);
напишем следующую
строчку:
fixed =
gtk_fixed_new();
Функция
gtk_fixed_new создаст для нас контейнер
GtkFixed.
Следующей
строчкой мы разместим только что
созданный контейнер в главном окне
программы . Кстати, главное окно — это
тоже виджет — контейнер для других
контейнеров или виджетов.
gtk_container_add(GTK_CONTAINER(window),
fixed);
Дальше создадим
кнопку с надписью «Move»
button =
gtk_button_new_with_label("Move");
Теперь подготовим
массив указателей, с именем data, для
дальнейшей передачи его в функцию —
обработчик нажатия кнопки.
Присвоим
указателям на структуру button_position адреса
переменных типа button_position:
p_bp1 = &bp1;
p_bp2 = &bp2;
Присвоим каждому
элементу массива типа gpointer преобразованные
указатели (тип gpointer) на структуру типа
button_position (с именами p_bp1 и p_bp2) и преобразованный
указатель (тип gpointer) на контейнер GtkFixed
(с именем fixed).
data[0] =
(gpointer)p_bp1;
data[1] =
(gpointer)p_bp2;
data[2] =
(gpointer)fixed;
Далее напишем
сигнал который свяжет событие («clicked»)
нажатия на кнопку (с именем button) с функцией
— обработчиком (с именем button_clicked).
g_signal_connect(button,
"clicked", G_CALLBACK(button_clicked), (gpointer)data);
Далее добавим
нашу кнопку (с именем button) в контейнер
GtkFixed (с именем fixed) в определенную позицию
(55, 10) в пикселях:
gtk_fixed_put(GTK_FIXED(fixed),
button, bp1.x, bp1.y);
Установим размер
кнопки в (85, 35) пикселях:
gtk_widget_set_size_request(button,
bs.width, bs.height);
Теперь рассмотрим
функцию — обработчик для нашей кнопки:
gboolean
button_clicked( GtkWidget *widget, gpointer data ) {
gpointer* data_t =
(gpointer*)data;
struct button_position
*p_bp1 = (struct button_position*)data_t[0];
struct button_position
*p_bp2 = (struct button_position*)data_t[1];
GtkWidget *fixed =
(GtkWidget*)data_t[2];
if (!f_switch) {
g_print("%d\n%d\n",
p_bp2->x, p_bp2->y);
gtk_fixed_move(GTK_FIXED(fixed),
widget, p_bp2->x, p_bp2->y);
f_switch = TRUE;
}
else {
g_print("%d\n%d\n",
p_bp1->x, p_bp1->y);
gtk_fixed_move(GTK_FIXED(fixed),
widget, p_bp1->x, p_bp1->y);
f_switch = FALSE;
}
return TRUE;
}
1) В качестве
параметров функция передает указатель
на виджет (GtkWidget *widget), в данном случае
виджет — кнопка (с именем button), который
вызвал функцию — обработчик, и указатель
на данные (с именем data). Функция возвращает
булево значение.
2) Далее мы
получаем указатели на структуру типа
button_position и указатель на контейнер
GtkFixed:
gpointer* data_t =
(gpointer*)data;
struct button_position
*p_bp1 = (struct button_position*)data_t[0];
struct button_position
*p_bp2 = (struct button_position*)data_t[1];
GtkWidget *fixed =
(GtkWidget*)data_t[2];
3) Дальше мы
проверяем значение переменной f_switch,
если она равна FALSE, то мы перемещаем
кнопку на новую позицию и меняем значение
f_switch на TRUE, иначе если f_switch равна TRUE, то
мы перемещаем кнопку в изначальное
положение и меняем f_switch на FALSE.
if (!f_switch) {
g_print("%d\n%d\n",
p_bp2->x, p_bp2->y);
gtk_fixed_move(GTK_FIXED(fixed),
widget, p_bp2->x, p_bp2->y);
f_switch = TRUE;
}
else {
g_print("%d\n%d\n",
p_bp1->x, p_bp1->y);
gtk_fixed_move(GTK_FIXED(fixed),
widget, p_bp1->x, p_bp1->y);
f_switch = FALSE;
}
Таким образом,
нажимая на кнопку, мы перемещаем кнопку
на другую позицию.
Рисунок
1. Изначальное положение кнопки
Рисунок
2. Измененное положение кнопки
Код
полностью:
#include <gtk/gtk.h> struct button_size { gint width; gint height; }; struct button_position { gint x; gint y; }; gboolean f_switch = FALSE; gboolean button_clicked( GtkWidget *widget, gpointer data ) { gpointer* data_t = (gpointer*)data; struct button_position
*p_bp1 = (struct button_position*)data_t[0]; struct button_position
*p_bp2 = (struct button_position*)data_t[1]; GtkWidget *fixed = (GtkWidget*)data_t[2]; if (!f_switch) { g_print("%d\n%d\n", p_bp2->x, p_bp2->y); gtk_fixed_move(GTK_FIXED(fixed), widget, p_bp2->x, p_bp2->y); f_switch = TRUE; } else { g_print("%d\n%d\n", p_bp1->x, p_bp1->y); gtk_fixed_move(GTK_FIXED(fixed), widget, p_bp1->x, p_bp1->y); f_switch = FALSE; } return TRUE; } int main( int argc, char **argv ) { GtkWidget *window; GtkWidget *button; GtkWidget *fixed; gpointer data[3]; struct button_size bs = { 80, 35 }; struct button_position bp1 = { 55, 10 }; struct button_position bp2 = { 55, 135 }; struct button_position *p_bp1; struct button_position *p_bp2; gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), "Gtk_p5"); gtk_window_set_position(GTK_WINDOW(window),
GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(window), 200, 200); gtk_container_set_border_width (GTK_CONTAINER (window), 10); g_signal_connect(window, "destroy",
G_CALLBACK(gtk_main_quit), NULL); fixed = gtk_fixed_new(); gtk_container_add(GTK_CONTAINER(window), fixed); button = gtk_button_new_with_label("Move"); p_bp1 = &bp1; p_bp2 = &bp2; data[0] = (gpointer)p_bp1; data[1] = (gpointer)p_bp2; data[2] = (gpointer)fixed; g_signal_connect(button, "clicked",
G_CALLBACK(button_clicked), (gpointer)data); gtk_fixed_put(GTK_FIXED(fixed), button, bp1.x, bp1.y); gtk_widget_set_size_request(button, bs.width, bs.height); gtk_widget_show_all(window); gtk_main(); return(0); }