接口
GtkTreeModel
弃用:4.10
描述 [源]
interface Gtk.TreeModel : GObject.Object
由GtkTreeView使用的树界面
GtkTreeModel
界面定义了一个通用的树界面,用于GtkTreeView小部件。它是一个抽象界面,旨在与任何适当的数据结构一起使用。程序员只需要在自己的数据类型上实现此接口,使其可由GtkTreeView小部件查看。
该模型表示为一个强类型、列式数据的有层次树。换句话说,该模型可以看作是一棵树,其中每个节点根据查询的列具有不同的值。列中数据的类型是通过使用GType系统确定的(即G_TYPE_INT
、GTK_TYPE_BUTTON
、G_TYPE_POINTER
等)。每个节点的类型在列之间是一致的。重要的是要注意,这个接口只提供了一种检查模型和观察变化的方式。每个模型的实现决定了如何以及是否进行更改。
为了使不需要编写自己专用模型的程序员的生活更加简单,提供了两个通用模型 —— GtkTreeStore
和 GtkListStore
。要使用这些模型,开发者只需要按照需要将数据推送到这些模型即可。这些模型提供了数据结构以及所有适当的树接口。因此,实现拖放、排序和数据存储变得很容易。对于大多数树和列表,这两个模型是足够的。
模型是在节点/列粒度上访问的。可以在某个节点和该节点的某个列上查询模型的值。用于在模型中引用特定节点的有两种结构。它们是GtkTreePath
和GtkTreeIter
(“iter”是迭代器的简称)。接口的大部分操作都是围绕GtkTreeIter
进行的。
路径本质上是一个潜在的节点。它是模型上的一个位置,可能实际上对应于特定模型的某个节点。GtkTreePath
可以转换为一个无符号整数数组或一个字符串。字符串形式是由冒号分隔的数字列表。每个数字表示那个级别的偏移。因此,路径0
表示根节点,而路径2:4
表示第三个节点的第五个子节点。
相比之下,GtkTreeIter
是对特定模型特定节点的引用。它是一个通用的结构,包含一个整数和三个通用指针。这些指针以模型特定的方式填充。可以通过调用gtk_tree_model_get_iter()将路径转换为迭代器。这些迭代器是访问模型的初级方式,类似于GtkTextBuffer
中使用的迭代器。它们通常在栈上静态分配,并且只短期使用。模型接口定义了一组操作,用于使用它们在模型中导航。
预期模型会使用私有数据填充迭代器。例如,内部为简单链表的GtkListStore
模型,在一个指针中存储一个列表节点。《code>GtkTreeModelSort在两个指针中存储一个数组和偏移量。此外,还有一个整数字段。这个字段通常在每个模型中填充一个唯一的戳记。这个戳记是为了捕获使用无效迭代器与模型相关的错误。
迭代器的生命周期一开始可能有点令人困惑。预期迭代器在模型未发生变化(并且没有发出信号)时始终有效。模型被认为拥有所有未解决的问题迭代器,并且从用户的角度来看不需要进行任何操作来释放它们。此外,一些模型保证迭代器在其引用的节点有效期间有效(最著名的是GtkTreeStore
和GtkListStore
)。虽然这通常不太有趣,但鉴于必须处理迭代器在信号之外可能不持续的情况,对排序模型进行了许多重要的性能增强。因此,添加了GTK_TREE_MODEL_ITERS_PERSIST
标志来指示这种行为。
为了帮助展示模型的一些常见操作,提供了一些示例。第一个示例展示了获取位置 3:2:5
处的 iter 的三种方式。虽然第一种方法较简单,但第二种方法更常用,因为您通常从回调中得到路径。
获取 GtkTreeIter
// Three ways of getting the iter pointing to the location
GtkTreePath *path;
GtkTreeIter iter;
GtkTreeIter parent_iter;
// get the iterator from a string
gtk_tree_model_get_iter_from_string (model,
&iter,
"3:2:5");
// get the iterator from a path
path = gtk_tree_path_new_from_string ("3:2:5");
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_path_free (path);
// walk the tree to find the iterator
gtk_tree_model_iter_nth_child (model, &iter,
NULL, 3);
parent_iter = iter;
gtk_tree_model_iter_nth_child (model, &iter,
&parent_iter, 2);
parent_iter = iter;
gtk_tree_model_iter_nth_child (model, &iter,
&parent_iter, 5);
第二个示例展示了快速遍历列表并从每行获取字符串和整数的快捷方法。下面使用的 populate_model()
函数未展示,因为它特定于 GtkListStore
。有关编写此类函数的信息,请参阅 GtkListStore
文档。
从 GtkTreeModel
读取数据
enum
{
STRING_COLUMN,
INT_COLUMN,
N_COLUMNS
};
...
GtkTreeModel *list_store;
GtkTreeIter iter;
gboolean valid;
int row_count = 0;
// make a new list_store
list_store = gtk_list_store_new (N_COLUMNS,
G_TYPE_STRING,
G_TYPE_INT);
// Fill the list store with data
populate_model (list_store);
// Get the first iter in the list, check it is valid and walk
// through the list, reading each row.
valid = gtk_tree_model_get_iter_first (list_store,
&iter);
while (valid)
{
char *str_data;
int int_data;
// Make sure you terminate calls to gtk_tree_model_get() with a “-1” value
gtk_tree_model_get (list_store, &iter,
STRING_COLUMN, &str_data,
INT_COLUMN, &int_data,
-1);
// Do something with the data
g_print ("Row %d: (%s,%d)\n",
row_count, str_data, int_data);
g_free (str_data);
valid = gtk_tree_model_iter_next (list_store,
&iter);
row_count++;
}
GtkTreeModel
接口包含两个引用计数的函数:gtk_tree_model_ref_node()
和 gtk_tree_model_unref_node()
。这两个方法是可选实现的。引用计数旨在作为一种方式,让视图让模型知道节点何时被显示。当节点可见时,GtkTreeView
会获取该节点的引用,这意味着节点位于顶层或已展开。显示并不意味着节点当前在视口中直接对用户可见。根据这种引用计数方案,缓存模型可以选择是否根据引用计数来缓存节点。基于文件系统的模型不想在内存中保留整个文件层次结构,只需保留当前每个视图中已展开的文件夹。
当使用引用计数时,必须注意以下规则:
-
从未拥有其父节点引用的情况下获取节点引用。这意味着所有父节点都必须被引用。
-
已删除节点的未解决引用不会被释放。这不可能做到,因为节点在接收行已删除信号时已经被删除。
-
模型不一定要向没有其兄弟节点被引用的行发出信号。换句话说,只有在节点被引用的水平上需要发出信号。然而,对于根级别,必须始终发出信号(然而,当任何视图附加时,根级别总是被引用)。
自 4.10 起已弃用
使用 GListModel
替换。
先决条件
为了实现 TreeModel,您的类型必须继承自GObject
。
接口结构
struct GtkTreeModelIface {
void (* row_changed) (
GtkTreeModel* tree_model,
GtkTreePath* path,
GtkTreeIter* iter
);
void (* row_inserted) (
GtkTreeModel* tree_model,
GtkTreePath* path,
GtkTreeIter* iter
);
void (* row_has_child_toggled) (
GtkTreeModel* tree_model,
GtkTreePath* path,
GtkTreeIter* iter
);
void (* row_deleted) (
GtkTreeModel* tree_model,
GtkTreePath* path
);
void (* rows_reordered) (
GtkTreeModel* tree_model,
GtkTreePath* path,
GtkTreeIter* iter,
int* new_order
);
GtkTreeModelFlags (* get_flags) (
GtkTreeModel* tree_model
);
int (* get_n_columns) (
GtkTreeModel* tree_model
);
GType (* get_column_type) (
GtkTreeModel* tree_model,
int index_
);
gboolean (* get_iter) (
GtkTreeModel* tree_model,
GtkTreeIter* iter,
GtkTreePath* path
);
GtkTreePath* (* get_path) (
GtkTreeModel* tree_model,
GtkTreeIter* iter
);
void (* get_value) (
GtkTreeModel* tree_model,
GtkTreeIter* iter,
int column,
GValue* value
);
gboolean (* iter_next) (
GtkTreeModel* tree_model,
GtkTreeIter* iter
);
gboolean (* iter_previous) (
GtkTreeModel* tree_model,
GtkTreeIter* iter
);
gboolean (* iter_children) (
GtkTreeModel* tree_model,
GtkTreeIter* iter,
GtkTreeIter* parent
);
gboolean (* iter_has_child) (
GtkTreeModel* tree_model,
GtkTreeIter* iter
);
int (* iter_n_children) (
GtkTreeModel* tree_model,
GtkTreeIter* iter
);
gboolean (* iter_nth_child) (
GtkTreeModel* tree_model,
GtkTreeIter* iter,
GtkTreeIter* parent,
int n
);
gboolean (* iter_parent) (
GtkTreeModel* tree_model,
GtkTreeIter* iter,
GtkTreeIter* child
);
void (* ref_node) (
GtkTreeModel* tree_model,
GtkTreeIter* iter
);
void (* unref_node) (
GtkTreeModel* tree_model,
GtkTreeIter* iter
);
}
没有可用的描述。
接口成员
row_changed |
|
当模型中的某一行发生变化时,发出该信号。 |
|
row_inserted |
|
当在模型中插入新行时,发出该信号。 |
|
row_has_child_toggled |
|
当某行获得第一个子行或失去最后一个子行时,发出该信号。 |
|
row_deleted |
|
当删除某行时,发出该信号。 |
|
rows_reordered |
|
当 |
|
get_flags |
|
获取此接口支持的 |
|
get_n_columns |
|
获取模型支持的列数。 |
|
get_column_type |
|
获取列的类型。 |
|
get_iter |
|
将iter设置为指向path的有效迭代器。 |
|
get_path |
|
获取由iter引用的新创建的 |
|
get_value |
|
初始化并将value设置为column处的值。 |
|
iter_next |
|
将iter设置为指向当前级别中跟随它的下一个节点。 |
|
iter_previous |
|
将iter设置为指向当前级别中的前一个节点。 |
|
iter_children |
|
将iter设置为指向parent的第一个子节点。 |
|
iter_has_child |
|
如果iter有子节点返回 |
|
iter_n_children |
|
获取iter的子节点数。 |
|
iter_nth_child |
|
使用给定的索引将iter设置为parent的子节点。 |
|
iter_parent |
|
将iter设置为child的父节点。 |
|
ref_node |
|
允许树引用节点。 |
|
unref_node |
|
允许树取消引用节点。 |