在我最近关于 GTK 4 中列表视图和模型的系列文章中,我有一个未完成的部分,即详细介绍 GtkColumnView。这很可能是本系列中最复杂的部分。我们正在进入 GtkTreeView 的核心地带——任何旨在取代其大部分功能的组件都将是一个复杂的野兽。
概述
正如我们对 GtkListView 所做的那样,我们将从一个高层次的概述和一个图片开始。
如果你回顾一下listview图片,你会记得我们使用列表项工厂为模型中需要显示的每个项目创建一个部件。
在列视图中,我们需要为每个项目提供多个部件——每个列一个。我们通过为每个列提供自己的列表项工厂来实现这一点。每当我们需要显示一个新项目时,我们会将每个列工厂的部件组合成新项目的一行。
在内部,列视图实际上是使用列表视图来保存行的。这很好,因为我在之前的文章中解释的所有关于项目重用以及如何使用列表项工厂的内容都同样适用。
当然,有些东西是不同的。例如,列视图必须组织大小分配,以便所有行中的部件对齐以形成适当的列。
注意:就像 GtkListView 一样,列视图仅为当前在视图中的模型部分创建部件,因此它共享垂直可扩展性。在水平方向上则不是这样——每一行都完全填充了每个列的部件,即使它们在左侧或右侧的视图之外。因此,如果你添加大量列,速度会变慢。
标题和其他复杂情况
列对象还包含其他数据,例如标题。列视图使用这些来显示每个列的标题。如果列视图被标记为可重新排序,则可以通过拖放标题部件来重新排列列。如果列被标记为可调整大小,则可以拖动两列之间的边界来调整其大小。
如果你注意到了,你现在可能会想知道这种调整大小与行中的单元格可以是任意部件并且希望至少有其最小大小可用于绘制其内容的事实如何结合起来。答案是我们正在使用 GTK 4 渲染机制的另一个新功能:部件可以控制如何处理其边界之外(由子部件)的绘制,通过
gtk_widget_set_overflow (cell, GTK_OVERFLOW_HIDDEN)
排序、选择以及对树视图对等性的追求
由于我们希望在功能上与 GtkTreeview 相匹配,因此我们尚未完成。用户喜欢在树视图中做的另一件事是单击标题,按该列对内容进行排序。GtkColumnView 标题也允许这样做。
你可能还记得上一篇文章中,排序是通过将你的数据包装在 GtkSortListModel 中,并为其提供合适的排序器对象来完成的。由于我们希望根据你单击的列标题具有不同的排序顺序,因此我们为每个列提供自己的排序器,你可以使用以下代码设置:
gtk_column_view_column_set_sorter (column, sorter)
但是我们如何从你刚刚单击的列中获取正确的排序器,并将其附加到排序模型?请记住,排序模型不会是我们传递给列视图的最外层模型,因为它始终是选择模型,因此列视图本身无法切换排序列表模型上的排序器。
我们想出的解决方案是让列视图提供一个在内部使用列排序器的排序器,通过:
gtk_column_view_get_sorter (view)
你可以在设置模型时将此排序器一次性提供给排序模型,然后当用户单击列标题以激活不同的列排序器时,一切都会自动更新。
这听起来很复杂,但它运行得非常好。这种方法的一个好处是,我们实际上可以一次按多个列进行排序——因为我们拥有所有可用的列排序器,并且我们知道你最后单击了哪个列。
相比之下,选择处理很容易。它的工作方式与 GtkListView 中相同。
总结
GtkColumnView 是一个复杂的部件,但我希望这一系列文章将使你更容易开始使用它。