【问题标题】:Make only some rows bold in a Gtk.TreeView在 Gtk.TreeView 中仅将某些行设为粗体
【发布时间】:2018-04-14 21:47:12
【问题描述】:

我想显示一行的状态已读未读,方法是将(行中的一列的)文本设为粗体或不是。

行的状态(或模型中的数据)可以是模型的一部分或其他地方。在这一点上我很灵活。

如何根据基础(动态)数据(在本例中为值1)使特定单元格的文本变为粗体?

#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class View(Gtk.TreeView):
    def __init__(self, model):
        Gtk.TreeView.__init__(self, model)
        col = Gtk.TreeViewColumn('Text',
                                 Gtk.CellRendererText(),
                                 text=0)
        self.append_column(col)
        # bold text
        # Gtk.CellRendererText(weight_set=True, weight=700),


class Model(Gtk.ListStore):
    def __init__(self):
        Gtk.ListStore.__init__(self, str, int)
        self.append(['foo 1', 0])
        self.append(['foo 2', 1])  # bold
        self.append(['foo 3', 0])
        self.append(['foo 4', 0])
        self.append(['foo 5', 1])  # bold

class Window(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.set_default_size(100, 200)

        # model & view
        self.model = Model()
        self.view = View(self.model)

        # layout
        self.layout = Gtk.Grid()
        self.add(self.layout)
        self.layout.attach(self.view, 0, 0, 1, 2)

        self.connect('destroy', Gtk.main_quit)
        self.show_all()

if __name__ == '__main__':
    win = Window()
    Gtk.main()

【问题讨论】:

  • 您是在问如何使文本变粗吗?
  • @Azsgy 这是问题的一部分。我不想让所有行都加粗 - 只有其中一些行,具体取决于那里的数据。
  • 好问题,顺便说一句,我花了一段时间才弄清楚。今天也学到了一些东西。

标签: python python-3.x gtk3 pygobject


【解决方案1】:

就像在 Gtk 中一样,这非常非常简单,只是不是很明显。您确实需要知道在哪里查看并仔细阅读相关文档。

class View(Gtk.TreeView):
    def __init__(self, model):
        Gtk.TreeView.__init__(self, model)
        renderer = Gtk.CellRendererText()
        col = Gtk.TreeViewColumn(
            'Text', renderer, text=0, weight_set=True)
        col.set_cell_data_func(renderer, datafunc)
        self.append_column(col)

第一个键是TreeViewColumn.set_cell_data_func method。这允许您设置一个拦截函数,您可以使用该函数在渲染之前修改单元格的属性。这是我写的一个例子,它可以满足你的要求:

def datafunc(col, renderer, model, titer, data):
    val = model.get_value(titer, 1)

    if val:
        renderer.set_property("weight", 700)

如您所见,它接收涉及的TreeViewColumnCellRendererTreeModelTreeIter,以及我已经省略的自定义数据。

第一步是获取当前列的值。为此,我们为模型提供 treeiter(它保存“当前行”,有点),以及我们想要的列 id(在本例中为第二列,1)。

剩下的很简单,我们使用该值来决定是否需要在 CellRenderer 上设置“权重”属性。

您在这里使用了 700,但为了清楚起见,我建议您使用 Pango.Weight.BOLD。这当然需要from gi.repository import Pango

【讨论】:

    【解决方案2】:

    在与 Gtk 维护人员进行简短讨论后,我发现还有另一种更简洁的方法可以做到这一点。由于这两个答案都有效,因此我决定将其作为单独的答案。

    另一个答案的问题是每行都调用cell_data_func。随着时间的推移,如果您有很多行,这将变得非常慢。

    这里的解决方案是在模型中添加另一列,然后绑定到相关属性。

    目前,您执行以下操作:

    col = Gtk.TreeViewColumn(
                'Text', renderer, text=0, weight_set=True)
    

    这会将CellRenderertext 属性绑定到模型的第0 列。

    现在,我们也可以将它绑定到任何其他属性。例如,将第 1 列绑定到 weight 属性:

    col = Gtk.TreeViewColumn(
                'Text', renderer, text=0, weight=1, weight_set=True)
    

    然后您可以将此列设置为不同的Pango.Weight 值以更改文本的粗细。

    class Model(Gtk.ListStore):
        def __init__(self):
            ...
            self.append(['foo 1', Pango.Weight.BOLD])
            self.append(['foo 2', Pango.Weight.BOOK])
            ...
    

    如果你想设置额外的属性,你也可以设置markup属性(它将字符串解析为pango标记并允许你更改文本某些部分的字体、颜色等)和@987654331 @ 属性,您可以使用 pango.AttrList 类型一次设置多个样式属性。

    【讨论】:

    • 非常感谢您的详细解答。但是这个(没有cell_data_fund)我不明白。
    • 知道了。 “将属性绑定到列”意味着:属性的值存储在模型中并从那里读取。对吗?
    • @buhtz 是的,准确地说。这是一个有点难以理解的概念。
    猜你喜欢
    • 1970-01-01
    • 2020-11-28
    • 1970-01-01
    • 1970-01-01
    • 2016-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-29
    相关资源
    最近更新 更多