模型(Model)

每一个Gtk::TreeView都有一个与之关联的Gtk::TreeModel,模型中包含了TreeView将要显示的数据。每个Gtk::TreeModel都可以被多个Gtk::TreeView使用。例如,这将允许以多种不同的方式同时显示和编辑一致的数据。也允许不同的视图显示同一个模型的不同列的数据,就像是多个SQL查询(或“视图”)显示同一个数据库表的不同字段一样。

理论上你可以实现自己的模型,但通常情况直接使用ListStoreTreeStore可以省略很多麻烦。

参考

10.1.1. 列表储存(ListStore)的行

ListStore包含简单的数据行,每个行都没有孩子。

Figure 10-1树形视图 - 列表储存

参考

10.1.2. 具有层次的树状储存

TreeStore包含数据行,并且每一行都可能有子行。

Figure 10-2树形视图 - 树状储存

参考

10.1.3. 模型列

TreeModelColumnRecord用于跟踪列和它们的数据类型。你TreeModelColumn实例添加到ColumnRecord,然后使用那些TreeModelColumns获取和设置模型列中的数据。你可能会发现,派生一个你自己的包含有TreeModelColumn数据成员的TreeModelColumnRecord会更方便。

class ModelColumns : public Gtk::TreeModelColumnRecord
{
public:

  ModelColumns()
    { add(m_col_text); add(m_col_number); }

  Gtk::TreeModelColumn<Glib::ustring> m_col_text;
  Gtk::TreeModelColumn<int> m_col_number;
};

ModelColumns m_Columns;

你可以在创建模型的时候指定ColumnRecord,如下所示:

Glib::RefPtr<Gtk::ListStore> refListStore =
    Gtk::ListStore::create(m_Columns);

TreeModelColumnRecord描述的是结构而不是数据,它可以在多个模型之间共享,这样效率更高。但是实例(例如此处的m_Columns)通常不是静态的,因为通常需要在glibmm初始化后示例化它。最好的解决方案是使他成为惰性初始化的单例,以便在第一个模型访问他的时候按需构造。

10.1.4. 添加行

使用append()prepend()insert()方法可以向模型添加行。

auto iter = m_refListStore->append();

你可以通过解引用迭代器获得行:

auto row = *iter;

10.1.4.1. 添加子行

Gtk::TreeStore模型可以存在子物件。可以通过append()prepend()insert()方法添加,如下所示:

auto iter_child =
    m_refTreeStore->append(row.children());

10.1.5. 设置值

你可以使用operator[]重载设置行中的特定列的数据,你需要使用创建模型时的TreeModelColumn指定列。

row[m_Columns.m_col_text] = "sometext";

10.1.6. 获取值

你可以使用operator[]重载获取行中特定列的数据,你需要使用创建模型时的TreeModelColumn指定列。

auto strText = row[m_Columns.m_col_text];
auto number = row[m_Columns.m_col_number];

如果你使用了不合适的类型,编译器会报错。例如,编译器将生成一个编译错误:

//compiler error - no conversion from ustring to int.
int number = row[m_Columns.m_col_text];

10.1.7. “隐藏”列

你可能想要将额外的数据和每一行关联。如果是这样,你只需要将其添加到模型的一个行中而不将其添加到视图中即可。