то виджит также будет разрушен.
Иногда нужно переместить виджит из одного контейнера в другой без его уничтожения. Это можно сделать так (мы будем перемещать надпись):
gtk_widget_ref(GTK_WIDGET(label));
gtk_container_remove(GTK_CONTAINER(cont1), label);
gtk_container_add(GTK_CONTAINER(cont2), label);
«Спрятать» виджит можно с помощью функции
void gtk_widget_hide(GtkWidget *w);
Отобразить виджит снова поможет функция gtk_widget_show().
Виджит может находиться в одном из состояний:
♦ GTK_STATE_NORMAL — нормальное;
♦ GTK_STATE_ACTIVE — активное (например, нажата кнопка);
♦ GTK_STATE_PRELIGTH — над виджитом находится указатель мыши;
♦ GTK_STATE_SELECTED — виджит выбран (установлен фокус ввода);
♦ GTK_STATE_INSENSITIVE — виджит не реагирует на ввод (сигналы).
Определить состояние виджита можно так:
GTK_WIDGET(w)->state
или с помощью макроса:
GTK_WIDGET_STATE(wid)
описанного в файле gtk/gtkwidget.h.
Сделать виджит неактивным можно так:
gtk_widget_set_sensitive(widget, FALSE);
Если второй параметр функции gtk_widget_set_sensitive() будет равен TRUE, виджит widget станет активным.
Чтобы наш виджит получил фокус ввода, нужно использовать функцию:
gtk_widget_grab_focus(widget);
23.4.2. Упаковка виджитов, поля ввода и кнопки
Для размещения (упаковки) виджита в окне используются контейнеры. Существуют два основных вида контейнеров. Первый вид в качестве прародителя использует объект класса GtkBin, а второй — объект класса GtkContainer. Контейнеры первого вида могут иметь только один дочерний виджит, поэтому они используются для создания специфических интерфейсов: одной кнопки, рамки, окна.
Контейнеры второго вида более функциональны — они могут иметь много дочерних виджитов. Чаще всего используются контейнеры:
♦ GtkHBox — позволяет размещать виджиты горизонтально;
♦ GtkVBox — используется для вертикального размещения виджитов;
♦ GtkFixed — позволяет размещать виджиты в фиксированных координатах;
♦ GtkTable — позволяет упаковывать виджиты в виде таблицы.
Наиболее удачным, на мой взгляд, является контейнер GtkTable, поэтому в этом параграфе мы рассмотрим именно его. GtkTable может с успехом заменить и горизонтальный, и вертикальный контейнеры — что нам стоит задать таблицу, состоящую или одной строки или одного столбца?
Кроме контейнера GtkTable, в этом параграфе будут рассмотрены:
♦ поля для ввода текста и обработка введенной информации;
♦ кнопки;
♦ файловый ввод/вывод.
Сейчас мы напишем небольшой конфигуратор, который будет вносить изменения в файл /etc/resolv.conf
. Напомню вам формат этого файла:
domain firma.ru
nameserver 192.168.0.1
nameserver 192.168.0.2
Директива domain определяет наш домен, а две директивы nameserver — первый и второй DNS- серверы, соответственно. Наш конфигуратор не будет вносить изменения в настоящий файл /etc/resolv.conf
— для этого нужны права суперпользователя. При желании можно будет потом скопировать файл resolv.conf
, сгенерированный нашей программой, в каталог /etc
.
На рисунке 23.2 изображена уже готовая программа. Работает она так. Когда пользователь введет что-нибудь в поле ввода и нажмет Enter, программа отобразит введенный им текст на консоли. Когда пользователь нажмет OK, введенная им информация будет еще раз выведена на консоль и записана в файл. При нажатии кнопки Quit программа завершит свою работу. Она должна также завершить работу при нажатии кнопки закрытия окна — в GTK программист сам определяет реакции на стандартные кнопки.
Рис. 23.3. Учебный конфигуратор
Как видно из рисунка, нам понадобятся три поля ввода, три надписи и две кнопки. Поля ввода мы будем хранить в массиве:
GtkWidget *edit[3];
Создать поле для ввода можно с помощью функции gtk_entry_new():
edit[i] = gtk_entry_new();
После создания поля необходимо вызвать функцию gtk_entry_set_editable(), иначе пользователь ничего не сможет ввести в это поле.
gtk_entry_set_editable(GTK_ENTRY(edit[i]), 1);
Ну и, само собой разумеется, нужно установить реакцию на нажатие клавиши Enter — сигнал activate:
gtk_signal_connect(GTK_OBJECT(edit[i]), 'activate',
GTK_SIGNAL_FUNC(enter_callback), edit[i]);
Весьма желательно на этапе отладки программы видеть введенную информацию на консоли. Для этого нужно написать такую функцию enter_callback(), которая выводила бы содержимое поля на консоль. Получить введенную пользователем информацию очень легко:
domain = gtk_entry_get_text(GTK_ENTRY(edit[0]));
dns1 = gtk_entry_get_text(GTK_ENTRY(edit[1]));
dns2 = gtk_entry_get_text(GTK_ENTRY(edit[2]))?
Реакция на нажатие кнопки OK будет следующей:
void writetofile(GtkWidget *widget, gpointer data) {
/* С помощью функции gtk_entry_get_text() мы получаем
введенный пользователем текст из полей ввода */
domain = gtk_entry_get_text(GTK_ENTRY(edit[0]));
dns1 = gtk_entry_get_text(GTK_ENTRY(edit[1]));
dns2 = gtk_entry_get_text(GTK_ENTRY(edit[2]));
/* Выводим прочитанный текст на консоль */
g_print('Domain %s
', domain);
g_print('DNS1 %s
', dns1);
g_print('DNS2 %s
', dns2);
/* Перезаписываем файл resolv.conf в текущем каталоге */
if ((resolv = fopen('resolv.conf','w')) == NULL) {
/* Наверное, нет места на диске или прав маловато... */