GtkTreeView
К этому моменту мы рассмотрели несколько простых виджетов GTK+, но не все виджеты представляют собой однострочные инструменты для ввода или отображения. Сложность виджетов ничего не ограничивается, и GtkTreeView
— яркий пример виджета, собравшего в себя огромный объем функциональных возможностей.
GObject
╰── GInitiallyUnowned
╰── GtkWidget
╰── GtkContainer
╰── GtkTreeView
GtkTreeView
— член семейства виджетов, создающий представление данных в виде дерева или списка наподобие тех, которые вы можете встретить в электронной таблице или файловом менеджере. С помощью виджета GtkTreeView
можно создать сложные представления данных, смешивая текст, растровую графику и даже данные вводимые с помощью виджетов GtkEntry
, и т. д.
Самый быстрый способ испытания GtkTreeView
— запуск приложения gtk3-demo
, которое поставляется вместе с GTK+ 3. Демонстрационное приложение показывает возможности всех виджетов GTK+ 3, включая GtkTreeView
(рис. 10.1)
Семейство GtkTreeView
состоит из четырех компонентов:
GtkTreeView
— отображение дерева или списка;GtkTreeViewColumn
— представление столбца или дерева;GtkCellRenderer
— управление отображаемыми ячейками;GtkTreeModel
— представление данных дерева и списка.
Первые три компонента формируют так называемое Представление, а последний — Модель. Концепция разделения Представление и Модели (часто называемая проектным шаблоном модель/Представление/Действие (Model/View/Controller или сокращенно MVC) не свойственна GTK+, но проектированию уделяется все большее и большее внимание на всех этапах программирования.
Ключевое достоинство проектного шаблона MVC заключается в возможности одновременной визуализации данных в виде разных представлений без ненужного их дублирования. Например, текстовые редакторы могу иметь две разные панели и редактировать разные фрагменты документа без хранения в памяти двух копий документа.
Шаблон MVC также очень популярен в Web-программировании, поскольку облегчает создание Web-сайтов, которые визуализируются в мобильных или WAP-обозревателях не так, как в настольных, просто за счет наличия отдельных компонентов Представление, оптимизированных для Web-обозревателя каждого типа. Вы также можете отделить логику сбора данных, например, запросов к базе данных, от логики пользовательского интерфейса.
Мы начнем с рассмотрения компонента модель, представленного в GTK+ двумя типами. Объект типа GtkTreeStore
содержит многоуровневые данные, например, иерархию каталогов, а объект GtkListStore
предназначен для простых данных.
Для создания объекта GtkTreeStore
в функцию передаётся количество столбцов, за которыми следуют типы всех столбцов:
GtkWidget *store = gtk_tree_store_new(3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_BOOLEAN);
Чтение, вставка, редактирование и удаление из модели выполняется с помощью структур GtkTreeIter
. Эти структуры итераторов указывают на узлы дерева (или строки списка) и помогают находить фрагменты структур данных потенциально очень большого объема, а также манипулировать ими. Есть несколько вызовов API для получения объекта-итератора для разных точек дерева, но мы рассмотрим простейшую функцию gtk_tree_store_append()
.
Перед тем как вставлять какие-либо данные в модель дерева, вам нужно получить итератор, указывающий на новую строку. Функция gtk_tree_store_append()
заполняет объект GtkTreeIter
, который представляет новую строку в дереве, как строку верхнего уровня (если вы передаете значение NULL в третьем аргументе), так и подчиненную или дочернюю строку (если вы передаете итератор главного или родительской строки):
GtkTreeIter iter;
gtk_tree_store_append(store, &iter, NULL);
Получив итератор, вы можете заполнять строку с помощью функции gtk_tree_store_set()
:
gtk_tree_store_set(store, &iter,
0, "Def Leppard",
1, 1987,
2, TRUE,
-1);
Номер столбца и данные передаются парами, которые завершаются -1
. Позже вы примените тип enum
для того, чтобы сделать номера столбцов более информативными.
Для того чтобы добавить ветвь к данной строке (дочернюю строку), вам нужен только итератор для дочерней строки, который вы получаете, вызвав снова функцию gtk_tree_store_append()
и указав на этот раз в качестве параметра строку верхнего уровня:
GtkTreeIter child;
gtk_tree_store_append(store, &child, &iter);
Дополнительную информацию об объектах GtkTreeStore
и функциях объекта GtkListStore
см. в документации API:
Пойдём дальше и рассмотрим компонент Представление типа GtkTreeView
.
Создание объекта GtkTreeView
сама простота: только передайте в конструктор в качестве параметра модель типа GtkTreeStore
или GtkListStore
:
GtkWidget *view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
Сейчас самое время настроить виджет для отображения данных именно так, как вы хотите. Для каждого столбца следует определить 'GtkCellRenderer` и источник данных. Можно выбрать, например, визуализацию только определенных столбцов данных или изменить порядок вывода столбцов.
'GtkCellRenderer` — это объект, отвечающий за прорисовку каждой ячейки на экране, и существует три подкласса, имеющие дело с текстовыми ячейками, ячейками пиксельной графики и ячейками кнопок-выключателей:
GtkCellRendererText
;GtkCellRendererPixBuf
;GtkCellRendererToggle
.
В вашем Представлении будет применено текстовое представление ячеек, GtkCellRendererText
.
GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_insert_column_with_attributes(
GTK_TREE_VIEW (treeview),
0, "This is the column title", renderer,
"text", COLUMN_ITEM_NUMBER,
NULL);
Вы создаете представление ячейки и передаете его в функцию вставки столбца. Эта функция позволяет сразу задать свойства GtkCellRendererText
, передавая заканчивающиеся значением NULL
пары “ключ/значение”. В качестве параметров указаны представление дерева, номер столбца, заголовок столбца, представление ячейки и его свойства. В приведенном примере вы задаёте атрибут “text”, передав номер других атрибутов, включая подчеркивание, шрифт, размер и т. д.
В примере далее, выполнив необходимые шаги, вы увидите, как это работает на практике.
Пример: использование виджета GtkTreeView
Введите следующий программный код и назовите файл gtk_tree.c
.
Примените тип
enum
для обозначения столбцов, чтобы можно было ссылаться на них по именам. Общее количество столбцов удобно обозначить какN_COLUMNS
:#include <gtk/gtk.h> enum { COLUMN_TITLE, COLUMN_ARTIST, COLUMN_CATALOGUE, N_COLUMNS }; void closeApp(GtkWidget *window, gpointer data) { gtk_main_quit(); } int main(int argc, char *argv[]) { GtkWidget *window; GtkTreeStore *store; GtkWidget *view; GtkTreeIter parent_iter, child_iter; GtkCellRenderer *renderer; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "Tree"); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(window), 300, 200); gtk_container_set_border_width(GTK_CONTAINER(window), 10); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(closeApp), NULL);
Далее вы создаёте модель дерева, передавая количество столбцов и тип каждого из них:
store = gtk_tree_store_new(N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
Следующий этап — вставка родительской и дочерней строк в дерево:
gtk_tree_store_append(store, &parent_iter, NULL); gtk_tree_store_set(store, &parent_iter, COLUMN_TITLE, "Dark Side of the Moon", COLUMN_ARTIST, "Pink Floyd", COLUMN_CATALOGUE, "B000024D4P", -1); gtk_tree_store_append(store, &child_iter, &parent_iter); gtk_tree_store_set(store, &child_iter, COLUMN_TITLE, "Speak to Me", -1); view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
Наконец, добавьте столбцы в представление, задавая источники данных для них и заголовки:
renderer = gtk_cell_renderer_text_new(); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), COLUMN_TITLE, "Title", renderer, "text", COLUMN_TITLE, NULL); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), COLUMN_ARTIST, "Catalogue", renderer, "text", COLUMN_ARTIST, NULL); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), COLUMN_CATALOGUE, "Catalogue", renderer, "text", COLUMN_CATALOGUE, NULL); gtk_container_add(GTK_CONTAINER(window), view); gtk_widget_show_all(window); gtk_main(); return 0; }
Назад: Виджеты класса GtkButton
Вернуться на главную страницу