16 мая 2009 г.

Несколько виджетов в окне. Часть 1. GtkVBox().

Одна строка в окне - это конечно, не серьёзно. Практически всегда в окно необходимо поместить 2 или более виджетов. Но если мы это сделаем обычным способом, о котором говорилось в Создание простого окна. Часть 1:
$window = new GtkWindow();
 
$window->add(new GtkLabel('Строка 1'));
$window->add(new GtkLabel('Строка 2'));
то получим ошибку:
Gtk-WARNING **: Attempting to add a widget with type
GtkLabel to a GtkWindow, but as a GtkBin subclass a
GtkWindow can only contain one widget at a time;
it already contains a widget of type GtkLabel


Это происходит потому, что GtkWindow() может содержать в себе только один виджет. В такие моменты необходимо использовать специальные контейнеры. Их существует несколько видов. Сегодня я расскажу о вертикальном контейнере GtkVBox(). В нём каждый новый виджет распологается под предыдущим. Он создаётся незамысловатой командой:
$vbox = new GtkVBox();


Для добавления в него виджетов используются методы pack_start() и pack_end(), которые помещают виджеты, соответственно, сверху вниз и снизу вверх. Первым параметром они принимают виджет, второй необязательный параметр отвечает за расширение ячейки по всему свободному пространству, а третий, также необязательный, отвечает за заполнение всего пространства ячейки виджетом.
$vbox->pack_start($label1, FALSE, FALSE);
$vbox->pack_end($label2, FALSE, FALSE);


Теперь остаётся только добавить контейнер в окно и вывести окно на экран. Как это делается, вы уже знаете из статьи Создание простого окна. Часть 1.

В итоге мы получим следующее:


На последок приведу полные код программы:
<?php
 
$window = new GtkWindow();
$window->connect_simple('destroy', array('Gtk', 'main_quit'));
$window->set_size_request(200, 100);
 
$vbox = new GtkVBox();
 
$label1 = new GtkLabel('Строка 1');
$label2 = new GtkLabel('Строка 2');
 
$vbox->pack_start($label1, FALSE, FALSE);
$vbox->pack_end($label2, FALSE, FALSE);
 
$window->add($vbox);
$window->show_all();
Gtk::main();
 
?>

7 комментариев:

Анонимный комментирует...

Огромное спасибо за блог! Пишите чаще, подписался на RSS :)

Анонимный комментирует...

Здравствуйте. У меня возник вопрос.
Допустим у нас есть два лейбла:
$label1 = new GtkLabel('Строка 1');
и
$label2 = new GtkLabel('Строка 2');
ещё есть кнопка
$button = new GtkButton('Нажать');

Есть вертикальный бокс (как у Вас в примере).
В верхней ячейке стоит виджет $label1,
а в нижней кнопка $button.
Задача такая: как в верхней ячейке поменять виджеты с $label1 на $label2, при нажатии на кнопку $button?
На мой взгляд решение не очевидно.

Shecspi комментирует...

Текст в лейбле меняется с помощью метода set_text(). В вашем случае второй GtkLabel() создавать нет необходимости, достаточно установить новый текст.

$label1 = new GtkLabel('Строка 1');
$button = new GtkButton('Нажать');
$button->connect_simple('clicked', 'on_button', $label1);

function on_button($label1)
{
$label1->set_text('Строка 2');
}

Анонимный комментирует...

Спасибо за ответ, но я не правильно сформировал мысль.
Что если GtkLabel в ячейке нужно заменить на, скажем, поле ввода GtkEntry?

Shecspi комментирует...

Я то же как-то заинтересовался подобным, но, к сожалению, так и не смог найти ответ на этот вопрос.
С удалением старого виджета проблем не возникает:
$button->connect_simple('clicked', 'on_button', $vbox, $label1, $label2);

function on_button($vbox, $label1, $label2)
{
$vbox->remove($label1);
}

А вот как на его место вставить новый я не знаю.

Анонимный комментирует...

Книга Pro PHP-GTK
http://letitbit.net/download/f4e910a66e/Pro_PHP_GTK___ISBN_1590596137.pdf.html
Выложил сегодня, 1 июня 2009 года.
Предлагаю начать её совместный перевод на родной, русский язык.

Shecspi комментирует...

Я бы с радостью, но, к сожалению, плохо знаю английский язык.

По поводу вашего (вашего?) предыдущего вопроса я всё-таки нашёл ответ. Ниже привожу полный код программы. Имеется две кнопки: одна только удаляет GtkLabel(), другая удалет и вместо него помещает GtkEntry().

$window = new GtkWindow();
$window->connect_simple('destroy', array('Gtk', 'main_quit'));
$window->set_size_request(300, 100);

// Основной контейнер
$vbox = new GtkVBox();

// Исходная строка
$item = new GtkVBox();
$item->pack_start(new GtkLabel('Строка 1'));

// Кнопки
$hbox = new GtkHBox();
$hbox->pack_start($button1 = new GtkButton('Удалить GtkLabel()'));
$hbox->pack_start($button2 = new GtkButton('Показать GtkEntry()'));
$button1->connect_simple('clicked', 'remove_label', $item);
$button2->connect_simple('clicked', 'show_entry', $item);

function remove_label($item)
{
foreach ($item->get_children() as $widget)
$item->remove($widget);
}

function show_entry($item)
{
remove_label($item);
$item->pack_start(new GtkEntry(), 0);
$item->show_all();
}

$vbox->pack_start($item, FALSE, FALSE);
$vbox->pack_end($hbox, FALSE, FALSE);

$window->add($vbox);
$window->show_all();
Gtk::main();