【问题标题】:Custom Gtk.CellRenderer with a Toggle cycling between True, None (displayed as inconsistent) and False, python GTK 3自定义 Gtk.CellRenderer,在 True、None(显示为不一致)和 False 之间循环切换,python GTK 3
【发布时间】:2020-04-18 19:51:20
【问题描述】:

我需要编写一个自定义的Gtk.CellRenderer(我们称之为CellRendererToogleWithNone),其行为类似于Gtk.CellRendererToggle,但不仅支持TrueFalse,我还希望它支持None应该显示为这样的不一致状态:

在切换时,我想以某种定义的顺序旋转,例如:True -> False -> None (但这可能是最容易的部分,我仍然认为我提到过)

我也不知道如何让它与 TreeStore 一起工作,因为如果我这样做了

self.treestore = Gtk.TreeStore.new(types = (bool,))
iter = self.treestore.append(parent = None, row = (None,))

它将任何None 值转换为False,因为bool 似乎不允许None

我没有在网上找到任何有用的自定义 Gtk.CellRenderer 示例。

我想通过继承 Gtk.CellRenderer 而不是继承 Gtk.CellRendererToggle 来做到这一点,因为这也可以作为一个有用的示例来实现更多像这样的单元格渲染器。

我只能猜测我必须为TreeStore 定义一些自定义数据类型,比如bool_or_none 而不是bool(也不知道该怎么做)并在其中保留我自己的Gtk.ToggleButton我的自定义CellRendererToogleWithNone

编辑 0:

This post 关于如何编写自定义 Gtk.CellRenderer 提供了一些提示,这些提示可能可以重复使用,但不能解决我的问题。它没有显示如何使 Gtk.TreeStore 接受 None 变量的 bool 值,我不明白那里的一切。它甚至不使用 Gtk.Button,而是似乎在我猜可能是父级的小部件内绘制了一个框。我不想画我自己的 Toggle,我想重用 Gtk.ToggleButton 和它的 inconsistent 属性

编辑 1:

由于自定义单元格渲染器似乎并不容易,我认为在 python 中查看一个最小的工作示例会特别有用。我还应该提到,我希望尽可能紧凑地显示数据,这不包括建议的解决方法,例如为一个值设置两个切换。

【问题讨论】:

  • 1) 您可以将值存储在 GVariant 中或创建具有 3 个可能值的自定义类,之后您可以创建类型为 object 的列。我不确定它是否必须是 GObject 子类。 2) 编写自定义 CellRenderers 并不是一件容易的事,因为它们不是传统的小部件,因为您必须手动渲染所有内容。请查看'CellRendererToggle source code` 以获取提示。
  • 3) 另一种方法是使用GtkCellRendererToggle 和两列:一列用于"active" 属性,一列用于"inconsistent"
  • @Alexander 感谢 GVariant 的提示。这正是我在这里问的原因。我似乎不太容易实现单元渲染器,所以我希望有人对它们有经验。关于您的第二条评论,我的目标之一是尽可能紧凑地显示数据,因此将切换数量翻倍对我来说实际上是不可能的。

标签: python toggle gtk3 gtktreeview


【解决方案1】:

问题:自定义Gtk.CellRendererToggle,在True、None(显示为不一致)和False之间循环切换。

您误会了,设置inconsistant 标志不是Gtk.CellRendererToggle 对象的一部分。它已经在那里实施了。您必须改为实现Gtk.TreeCellDataFunc

我也希望它支持None

我无法使用 None 值,
因此我使用带有值的类型int[False, True, 2]

注意

  • def on_toggle(...) 中,model 值更改为0 == False1 == True。如果您希望它保持boolean 类型,请相应地实施。
  • 您应该知道,2 的值也等于 True


参考

  • Gtk.TreeViewColumn.set_cell_data_func

    这个函数用来代替标准的属性映射来设置列值,应该适当设置self的单元格渲染器的值。

  • Gtk.TreeCellDataFunc

    设置单元格属性的函数,而不仅仅是使用单元格和模型之间的直接映射。这对于自定义单元格渲染器很有用


实现:核心点:.set_cell_data_func(cell_renderer, .set_status)

class TreeViewColumnTriState(Gtk.TreeViewColumn):

    def __init__(self, title='', model=None, **attributes):
        cell_renderer = Gtk.CellRendererToggle()
        cell_renderer.connect("toggled", self.on_toggle, model)

        self.inconsistent = attributes.pop('inconsistent', None)
        super().__init__(title, cell_renderer, active=0, **attributes)
        self.set_cell_data_func(cell_renderer, self.set_status)

    def set_status(self, column, cell, model, _iter, *ignore):    
        if model.get_value(_iter, 0) == self.inconsistent:
            cell.set_property('inconsistent', True)
        else:
            cell.set_property('inconsistent', False)

    def on_toggle(self, cell, path, model, *ignore):
        if path is not None:
            model = model[model.get_iter(path)]    
            model[0] += 1
            if model[0] == 3:
                model[0] = 0

用法

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib


class App(Gtk.ApplicationWindow):
    def __init__(self):
        super().__init__()
        self.connect("destroy", Gtk.main_quit)

        model = Gtk.ListStore(int)

        #  Some initial data
        for n in [False, True, 2]:
            model.append([n])

        col = TreeViewColumnTriState("Foo", model, inconsistent=2)

        tv = Gtk.TreeView(model)
        tv.append_column(col)
        self.add(tv)

        self.show_all()


if __name__ == "__main__":
    main = App()
    Gtk.main()

用 Python 测试:3.5 - gi.__version__:3.22.0

【讨论】:

  • 在仔细查看并使用代码后,我接受了您的回答。你是对的,我误解了一些事情。我不需要实现 CellRenderer,我可以像您在示例中那样使用 CellRendererToggle。实现 CellRenderer 意味着我需要绘制自己的切换,这与我重用现有切换的愿望相矛盾。我的 TreeStore 仍然不接受 None 值,但我觉得我应该在这一点上提出一个单独的问题。现在代替 int,我坚持使用 bool,但做了一些诡计,所以我不需要依赖 TreeStore on None。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多