25 июня 2009 г.

Отображение списков. Часть 1

Мы начинаем знакомство с большой темой - отображением списков.

Сегодня будет разработана простая программа, дающая представление о данной теме и являющаяся основой для последующих статей.



Сначала необходимо создать модель списка. Это некая структура, хранящая в себе все данные, которые необходимо поместить в список. При её создании нужно указать тип колонки. Их существует 15 видов, но в большинстве случаев достаточно одного строкового - GObject::TYPE_STRING. С полным списком типов можете ознакомиться здесь (правда там устаревшая документация, вместо Gtk:: нужно использовать GObject::). Количество параметров, передаваемых данному классу должно быть равно количеству колонок.
$store = new GtkListStore(GObject::TYPE_STRING, GObject::TYPE_STRING);


Теперь нужно заполнить модель. Для этого предназначен метод append(), которому передаётся массив, содержащий добавляемые данные. Один вызов append() добавляет в модель одну строчку. Мы же добавим три:
$store->append(array('1.1', '1.2'));
$store->append(array('2.1', '2.2'));
$store->append(array('3.1', '3.2'));


Для отображения модели в окне используется класс GtkTreeView:
$view = new GtkTreeView($store);


У нас уже есть готовая модель и виджет, отображающий её. Остаётся только создать две колонки, т.к. без них GtkTreeView бесполезен. Для их создания используем класс GtkTreeViewColumn, которому первым параметром передаётся имя колонки; вторым - объект GtkCellRendererText, предназначенный для отображения текстовой информации в колонке; третьим - аттрибут, имеющий значение 'text' для GtkCellRendererText; четвёртым - целочисленный идентификатор колонки. Затем методом append_column() добавим созданную колонку в GtkTreeView.
$render = new GtkCellRendererText;
$view->append_column(new GtkTreeViewColumn('Колонка 1', $render, 'text', 0));
$view->append_column(new GtkTreeViewColumn('Колонка 2', $render, 'text', 1));


Для того, чтобы большие объёмы данных не выходили за пределы окна поместим GtkTreeView в область с полосами прокрутки. О том, как это сделать описано в статье Полосы прокрутки.

Полный код программы:
<?php
 
$window = new GtkWindow;
$window->set_size_request(200, 100);
$window->connect_simple('destroy', array('Gtk', 'main_quit'));
 
$store = new GtkListStore(GObject::TYPE_STRING, GObject::TYPE_STRING);
$store->append(array('1.1', '1.2'));
$store->append(array('2.1', '2.2'));
$store->append(array('3.1', '3.2'));
 
$view = new GtkTreeView($store);
 
$render = new GtkCellRendererText;
$view->append_column(new GtkTreeViewColumn('Колонка 1', $render, 'text', 0));
$view->append_column(new GtkTreeViewColumn('Колонка 2', $render, 'text', 1));
 
$scroll = new GtkScrolledWindow();
$scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
$scroll->add($view);
 
$window->add($scroll);
$window->show_all();
Gtk::main();
 
?>

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

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

Привет. Я только-только хотел попросить тебя рассказать про таблицы (Grid'ы), а ты уже всё написал. Ща почитаем )))

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

У меня ещё один вопрос: можно ли конструктору класса GtkListStore передавать массив параметров, вместо перечня?

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

Нет, массивы в данном случае не допустимы, поддерживается только простое перечисление.

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

Я зарегился, теперь ты можешь знать, кто тебя всё время о чём-то спрашивает )))
Дык вот, к продолжению о предыдущем вопросе.
На мой взгляд очень удобно взять из базы заголовки колонок и поместить их прямо в GtkListStore массивом. Если такое не возможно, может есть какие-нибудь мысли по этому поводу?
Если у меня что-то появится - отпишу.

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

то есть я имел в виду, в цикле взять у каждой колонки тип и прописать его...

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

Конструктору GtkListStore передаются только типы колонок, а заголовки указываются первым параметром к GtkTreeViewColumn.

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

Это будет выглядеть примерно так:
// $array - массив с именами колонок. Они берутся из базы.
$array = array('Колонка 1', 'Колонка 2');
foreach ($array as $value)
$view->append_column(new GtkTreeViewColumn($value, $render, 'text', 0));

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

Да, я это понимаю, но вот как быть с типами колонок?

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

Хм... Даже не знаю. По моему, это никак не реализовать.

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

То есть универсальному классу Table, которому нужно передать два массива: заголовки с типами, и данные - не суждено увидеть свет... Жаль.

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

Интересный эффект наблюдаю у себя: строка заголовков и первая строка данных в таблице - двойной размер по высоте.
Есть ли какие-нибудь средства выравнивания в колонках и заголовках?

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

Можно скриншот этого "безобразия, код и ОС?

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

Ооо... Я разобрался, в чём была причина неадекватного поведения таблицы. Дело в том, что я брал данные из файла, где каждая строка в конце имеет скрытый символ "перевод каретки". Вот этот перевод каретки и портил всю картину.
Ос: Win32

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

Теперь другой вопрос: как автоматически задать ширину окна до ширины таблицы?

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

Из-за того, что используются полосы прокрутки, окно будет принимать минимально возможные размеры. Если убрать секцию с GtkScrolledWindow и напрямую поместить GtkTreeView в окно, то оно примет размеры, необходимые для отображения списка.

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

по поводу типов колонок в конструкторе:

call_user_func_array(array($obj, '__construct'), $args)

$args - массив параметров для конструктора

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

А так не лучше?
$store = new GtkTreeStore();
$store->set_column_types($types);

while ($row = pg_fetch_row($result)) {
$store->append(null, $row);
}