视图

视图实际上是一个用于显示模型(Gtk::TreeModel)数据并允许用户与其交互的部件(Gtk::TreeView)。视图可以显示模型的所有列也可以只显示一部分列还可以以不同的方式显示列。

参考

10.2.1. 使用模型

你可以在构造Gtk::TreeView的时候为其指定一个Gtk::TreeModel,也可以构筑完成后使用set_model()方法指定,如下所示:

m_TreeView.set_model(m_refListStore);

10.2.2. 为视图添加列

你可以使用append_column()方法告知视图以一定的顺序于某个列标题下显示模型的某个列。

m_TreeView.append_column("Messages", m_Columns.m_col_text);

当使用这种简单的append_column()重载的时候,TreeView将会使用适当的CellRenderer显示模型数据。例如将字符串和数字显示在简单的Gtk::Entry部件中,布尔量使用Gtk::CheckButton显示。这通常是你所希望的行为。对于其他类型的行,你必须使用TreeViewColumn::set_cell_data_func()连接一个将你的类型转换为字符串表示形式的回调,或者是从CellRenderer派生一个合适的类。请注意,默认情况下(unsigned) short不被支持 - 作为替代你可以使用(unsigned) int或者(unsigned) long作为行类型。

10.2.3. 每个视图列不不止一个模型列

要在一个视图列中呈现多个模型列,你需要手动创建TreeView::Column部件,并使用pack_start()方法向其添加模型列。

然后使用append_column()将视图列添加到视图中。请注意,Gtk::TreeView::append_column()被重载为接受预建的Gtk::TreeView::Column部件,或者只接受由TreeModelColumn生成的合适的Gtk::TreeView::Column部件。

这是一些示例代码,在同一列中有一个像素缓冲区(pixbuf)图标和一个文本名:

auto pColumn = Gtk::make_managed<Gtk::TreeView::Column>("Icon Name");

// m_columns.icon and m_columns.iconname are columns in the model.
// pColumn is the column in the TreeView:
pColumn->pack_start(m_columns.icon, /* expand= */ false);
pColumn->pack_start(m_columns.iconname);

m_TreeView.append_column(*pColumn);

10.2.4. 指定单元格渲染器(CellRenderer)详情

默认的CellRenderers及其默认行为通常已经足够好了,但是有时你需要更精细的控制它。例如来自gtkmm/demos/gtk-demo/example_treeview_treestore.cc的示例代码,附加一个Gtk::CellRenderer部件并指示其各个模型列的外观的各个方面来呈现数据。

auto cols_count = m_TreeView.append_column_editable("Alex", m_columns.alex);
auto pColumn = m_TreeView.get_column(cols_count-1);
if(pColumn)
{
  auto pRenderer = static_cast<Gtk::CellRendererToggle*>(pColumn->get_first_cell());
  pColumn->add_attribute(pRenderer->property_visible(), m_columns.visible);
  pColumn->add_attribute(pRenderer->property_activatable(), m_columns.world);

你还可以通过连接到CellRenderer的信号以检测用户的操作。例如:

auto pRenderer = Gtk::make_managed<Gtk::CellRendererToggle>();
pRenderer->signal_toggled().connect(
    sigc::bind( sigc::mem_fun(*this,
        &Example_TreeView_TreeStore::on_cell_toggled), m_columns.dave)
);

10.2.5. 可编辑单元格

10.2.5.1. 自动储存的可编辑单元格

用户可以就地编辑TreeView中的单元格。若要如此,请使用Gtk::TreeViewinsert_column_editable()append_column_editable()方法而不是insert_column()append_column()方法。编辑单元格后新的值将立刻储存在模型中。请注意,这些方法是模版,只能为简单的列类型实例化(例如,Glib::ustringintlong)。

10.2.5.2. 为可编辑单元格实现自定义逻辑。

但是你可能不希望立刻储存新的值。例如你可能希望对输入进行检测,符合预期的范围才储存。

为此,你应该使用常规的Gtk::TreeView::insert_column()Gtk::TreeView::append_column()方法,然后使用get_column_cell_renderer()方法获取该列使用的Gtk::CellRenderer

然后你应该讲Gtk::CellRenderer*转换为你期望的特定版本的CellRenderer(例如转换为CellRendererText,以便调用特定的API。

例如,对于CellRendererText,你应该将单元格的editable属性设置为true,如下所示:

cell->property_editable() = true;

对于CellRendererToggle,你应该改为设置activatable属性。

你可以连接到适当的"edited"信号。例如,连接到Gtk::CellRendererText::signal_edited()或者是Gtk::CellRendererToggle::signal_toggled()。如果该列包含多个CellRenderer,则你需要在视图上使用Gtk::TreeView::get_column()方法然后再调用get_cells()获取目标单元格。

在你的信号处理函数中,你应该检查新值如果其对于你的应用程序而言是合适的则将其储存到你的模型中。