简体   繁体   English

在Gtk.TreeView中只创建一些粗体行

[英]Make only some rows bold in a Gtk.TreeView

I want to display the status read or unread of a row by makeing the text (of a column in the row) bold or not. 我想通过使文本(行中的列) 加粗或不加来显示行的读取或未状态。

The status of the row (or the data in the model) can be part of the model or somewhere else. 行的状态(或模型中的数据)可以是模型的一部分或其他位置。 I am flexible at this point. 我现在很灵活。

How can I make the text of a specific cell bold depending on the underlying (dynamic) data, which is in this example the value 1 ? 如何根据底层(动态)数据使特定单元格的文本变为粗体,在此示例中,值为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()

After a short discussion with the Gtk maintainers, I've found that there is another, cleaner way to do this. 在与Gtk维护人员进行简短讨论之后,我发现有另一种更清洁的方法可以做到这一点。 Since both answers work, I've decided to put this as separate answer. 由于这两个答案都有效,我决定将其作为单独的答案。

The problem with the other answer is that the cell_data_func gets called for every row. 另一个答案的问题是每行调用cell_data_func Over time, this will get really slow if you have many rows. 随着时间的推移,如果你有很多行,这将变得非常慢。

The solution here is to add another column to your model that you then bind to the relevant attribute(s). 这里的解决方案是在模型中添加另一列,然后绑定到相关属性。

Currently, you do the following: 目前,您执行以下操作:

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

This binds the text property of the CellRenderer to column 0 of your model. CellRenderertext属性绑定到模型的第0列。

Now, we can bind this to any other property too. 现在,我们也可以将它绑定到任何其他属性。 For example, bind column 1 to the weight property: 例如,将列1绑定到weight属性:

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

You can then set this column to different Pango.Weight values to change the weight of the text. 然后,您可以将此列设置为不同的Pango.Weight值以更改文本的权重。

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

If you want to set additional properties, you can also set the markup property (which parses the string as pango markup and allows you to change the font, color, etc of some parts of the text) and the attributes property, which you can use to set many style attributes at once with the pango.AttrList type. 如果要设置其他属性,还可以设置markup属性(将字符串解析为pango标记并允许您更改文本某些部分的字体,颜色等)和attributes属性,您可以使用使用pango.AttrList类型一次设置许多样式属性。

As is often in Gtk, this is very very simple, just not very obvious. 和Gtk一样,这非常简单,不是很明显。 You really need to know where to look and read the related docs carefully. 您确实需要知道在哪里查看并仔细阅读相关文档。

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)

The first key is the TreeViewColumn.set_cell_data_func method . 第一个键是TreeViewColumn.set_cell_data_func 方法 This allows you to set an intercept function that you can use to modify the properties of the cell before it is rendered. 这允许您设置一个拦截函数,您可以使用该函数在渲染之前修改单元格的属性。 Here's an example one I wrote which does what you want: 这是我写的一个例子,可以满足您的需求:

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

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

As you can see, it receives the TreeViewColumn , CellRenderer , TreeModel and TreeIter involved, as well as custom data, which I've ommited. 如您所见,它接收到所涉及的TreeViewColumnCellRendererTreeModelTreeIter ,以及我已经省略的自定义数据。

The first step is to get the values of the current column. 第一步是获取当前列的值。 For that, we give the model the treeiter (which saves the "current row", kinda), and the column id we want (in this case the second column, 1 ). 为此,我们为模型提供了treeiter(保存了“当前行”,有点)和我们想要的列id(在本例中为第二列, 1 )。

The rest is pretty simple, we use that value to decide if we need to set the "weight" property on the CellRenderer. 其余的很简单,我们使用该值来决定是否需要在CellRenderer上设置“weight”属性。

You used 700 here, but I'd recommend you to use Pango.Weight.BOLD instead for clarity. 你在这里使用了700,但为了清晰起见,我建议你使用Pango.Weight.BOLD This requires from gi.repository import Pango of course. 这需要from gi.repository import Pango当然。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM