在我最近关于 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 是一个复杂的小部件,但我希望这一系列文章能让你更容易上手。