Шаг 6 - Контейнеры

Чаще всего, когда создается диалоговое окно, предполагается, что в нем будет находится более одного виджета. При программировании в WinAPI координаты этих виджетов задаются вручную. То есть напрямую координатами - габариты и координаты левой верхней точки объекта. Так как у пользователей может быть разное разрешение, то возникает неприятный эффект несоответстия позиций сгруппированных виджетов. Соответственно, если пользователь хочет изменить размеры диалогового окна, то последствия вообще не поддаются описанию. Ну, против этого естественно есть средства - подгонять координаты под разные разрешения и фиксирование размеров окна.

Ужас. Так чем же отличается GTK в этом плане от Виндов? Своеобразная теория контейнеров предполагает создание сетки, относительно которой будут выравниваться виджеты. Сетка распределяется относительно размеров окна. То есть, можно просто сказать - сетка 4 на 8, тогда размер каждой ячейки будет [ширина окна]/4 x [высота окна]/8. При изменении размеров автоматически будут перемещаться и виджеты. Впрочем, это зависит от соответствующих аргументов функций. А, еще они невидимы, что тоже не так уж плохо...

Такие виджеты, называемые также контейнерами или "упаковывающими виджетами" (packing widgets), бывают трех видов - вертикальные колонны, горизонтальные ряды и таблицы. Строго говоря, основная разница между ними в способе выравнивания и распределения упаковываемых виджетов.

Для начала приведу очень простой пример распределения полей ввода и меток. Надо сказать, что мне немного надоело писать все на простом C. Поэтому следующий файл будет написан на C++. Сохранить его надо будет как .cpp, .C, или .cc. Как угодно... Команда компиляции таже самая - gcc -Wall `gtk-config --libs --cflags` [имя файла] -o [имя исполнимого файла].

#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>


void delete_event (GtkObject * object)
{
	gtk_main_quit ();
};

int main (int argc, char *argv[])
{
	GtkWidget *window;
	GtkWidget *edit[5];
	GtkWidget *label[5];
	GtkWidget *vbox;

	char str[] = "Edit x";
	gtk_init (&argc, &argv);

	vbox = gtk_vbox_new (0, 0);

	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

	//Никогда не забывайте устанвливать этот обработчик
	gtk_signal_connect_object (GTK_OBJECT (window), "delete_event",
		GTK_SIGNAL_FUNC (delete_event), NULL);

	//Вы же не хотите, чтобы элементы прилипали к краям?
	gtk_container_set_border_width (GTK_CONTAINER (window), 10);

	//Создаем и упаковываем по пять меток и пять полей ввода...
	for (int i = 0; i < 5; i++)
	{
		edit[i] = gtk_entry_new ();
		sprintf (str, "Edit %d", i);
		label[i] = gtk_label_new (str);

		//Загоняем сначала метку, а затем и поле ввода в контейнер
		gtk_box_pack_start (GTK_BOX (vbox), label[i], TRUE, 0, 5);
		gtk_box_pack_start (GTK_BOX (vbox), edit[i], TRUE, 0, 5);
		gtk_widget_show (edit[i]);
		gtk_widget_show (label[i]);
	};

	//Чтобы добавить контейнер в окно...
	gtk_container_add (GTK_CONTAINER (window), vbox);

	gtk_widget_show (window);
	gtk_widget_show (GTK_WIDGET (vbox));

	gtk_window_set_title (GTK_WINDOW (window), "Step 6");

	gtk_main ();
	return 0;
};

У меня все это отобразилось так:

gif/6_1.gif (8777 b)

Обратили внимание, как лекго все это расположилось на равном расстоянии! Впрочем, это расположение можно контролировать. Для этого есть много параметров, я бы даже сказал, слишком много. Подробно мы эти функции рассмотрим в следующем шаге.


Загрузить проект | Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Аванесов Самвел - 23.07.2002