【问题标题】:Setting a single row of a CellRendererToggle to inconsistent将 CellRendererToggle 的单行设置为不一致
【发布时间】:2013-02-07 21:32:48
【问题描述】:

在 Gtk+3 上,我使用 TreeModel 来存储嵌套信息,并使用 CellRendererTextCellRendererToggle 显示它。用户可以点击每个切换按钮,当有嵌套的按钮并且它们处于不同状态时,我希望上层的按钮反映“不一致”状态。如何为 一个元素 设置此属性?

为了更清楚起见,我想通过 Transmission bittorrent 客户端实现的示例:

我知道如何将单元格渲染器的所有按钮设置为与myCellRendererToggle.set_properties(inconsistent=True) 不一致的状态,但我似乎无法从这里访问单个元素;

我知道如何访问我的 TreeStore 模型的特定行,但我只能设置 «True» 和 «False» 值。

我的代码与官方文档非常接近,因此您可以帮助我:https://python-gtk-3-tutorial.readthedocs.org/en/latest/cellrenderers.html#cellrenderertoggle(我使用 treeStore 而不是 listStore)

这是我的代码:

class HelloMyApp:

def __init__(self):

    # Set the Glade file
    self.builder = Gtk.Builder()
    self.builder.add_from_file(GLADEFILE)


    dic = {
        "on_button1_clicked" : self.btnValidate_clicked,
        "on_MainWindow_destroy" : self.quit,
        "on_window1_delete_event" : self.quit,

        }

    self.builder.connect_signals(dic)

    window = self.builder.get_object("window1")

    treeview1 = self.builder.get_object("treeview1")

    ######## This is my model : it stores a string and a boolean. #########
    self.treeModel = Gtk.TreeStore(str, bool)

    # Example on how to insert data in the model
    treeIter = self.treeModel.append(None, ['example one', True])
    self.treeModel.append(treeIter, [' simple elt', True])
    treeIter = self.treeModel.append(treeIter, ['example two', False])
    self.treeModel.append(treeIter, ['under example two', True])


    select = treeview1.get_selection()
    select.set_mode(Gtk.SelectionMode.BROWSE)

    select.connect("changed", self.on_tree_selection_changed, buf) 

    # Using one column of text and another column with the toggle buttons
    renderer = Gtk.CellRendererText()
    column = Gtk.TreeViewColumn("Title", renderer, text=0)
    treeview1.append_column(column)

    ######  Here is the CellRendereToggle  ################
    renderer_toggle = Gtk.CellRendererToggle()
    renderer_toggle.connect("toggled", self.on_cell_toggled)
    column_toggle = Gtk.TreeViewColumn("Installer", renderer_toggle, active=1)
    treeview1.append_column(column_toggle)

    treeview1.set_model(self.treeModel)


    window.show_all()


if __name__ == "__main__":

    HelloMyApp = HelloMyApp()
    Gtk.main()

谢谢!

编辑:回答 Marcus:我想不通,当我在函数内更改 CellRendererToggle 的属性时,它会更改每一行。

编辑解决方案:正如 Marcu 指出的那样,我们必须在每种情况下都设置属性,这就是我添加 else 部分的原因。

def cellRenderer_func(column, cellRenderer, treeModel, treeIter, userData):
    if 'cat' in treeModel.get_value(treeIter, 0): 
        # it happens only ones in my model, 
        # so here I am in a row I want to change to inconsistent.
        cellRenderer.set_property('inconsistent',True) 
        # I was expecting that changes the box of that row but it affects every row. 

    else: 
        cellRenderer.set_property('inconsistent', False) # and that's ok now.

我必须再试一次。 我想知道……我们真的必须手动完成吗,难道不是 treeView 的开箱即用功能吗?

【问题讨论】:

  • 我添加了一些示例代码(我是 Python 爱好者,但我希望它能够说明问题)。如果第一个文本列的值为“不一致”,则切换列也设置为不一致。如果第一列的文本具有“一致”值,则切换列设置为“正常”状态(根本不切换)。

标签: python gtk gtk3


【解决方案1】:

可以通过使用单元格数据函数来设置一个元素的属性。由于我只在 C 中完成此操作,因此只能将 PyGTK 文档的链接传递给您,我还没有看到 PyGObject 的此功能的相关文档。

对于 PyGTK 已记录在 herethis 页面底部为您提供了一个示例,this 文档中还介绍了 PyGTK 的单元格数据函数的使用。

例如,如果您想执行与传输相同的操作,您可以执行以下操作: 由于您收到当前迭代器作为单元格数据函数的参数,因此您可以循环遍历其所有子节点并检查子节点的状态。然后,您将知道在父节点上设置哪个状态。现在主要的一点是,在单元格数据函数中设置一个属性只会影响这个单个单元格,而不是树视图的所有元素。

我还可以为您提供我自己的应用程序的可视化示例:

我在此树视图中有“值”列。如果“菜单元素”列中的值设置为“启用”并且“类型”列中的值是“选项”,则会显示一个复选框而不是文本(我已经突出显示了这一行)。示例图像还显示了一个活动搜索,它突出显示了搜索结果。两者都可以使用单元格数据函数来设置您在问题中要求的一个元素的属性。

编辑

我已经完成了一些示例代码。要点是始终为每个单元格设置单元格属性。所以不仅仅是“如果……,那么设置属性”,而是“如果,像这样设置属性,否则,像那样设置属性”。 (它基于旧的 PyGTK 文档,但无论如何它应该澄清一些事情)。

#!/usr/bin/env python

# example basictreeview.py

import pygtk
pygtk.require('2.0')
import gtk

class BasicTreeViewExample:

    def set_status(self, column, cell, model, iter):
        if 'inconsistent' in model.get_value(iter, 0):
            cell.set_property('inconsistent',True) 
        else:
            cell.set_property('inconsistent',False)
        return

    def delete_event(self, widget, event, data=None):
        gtk.main_quit()
        return False

    def __init__(self):
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)

        self.window.set_title("Basic TreeView Example")

        self.window.set_size_request(200, 200)

        self.window.connect("delete_event", self.delete_event)

        self.treestore = gtk.TreeStore(str)

        for parent in range(4):
            piter = self.treestore.append(None, ['parent %i' % parent])
            for child in range(3):
                if child == 1:
                    self.treestore.append(piter, ['consistent'])
                else:
                    self.treestore.append(piter, ['inconsistent'])

        self.treeview = gtk.TreeView(self.treestore)

        self.tvcolumn0 = gtk.TreeViewColumn('Column 0')
        self.tvcolumn1 = gtk.TreeViewColumn('Column 1')

        self.treeview.append_column(self.tvcolumn0)
        self.treeview.append_column(self.tvcolumn1)

        self.text = gtk.CellRendererText()
        self.toggle = gtk.CellRendererToggle()

        self.tvcolumn0.pack_start(self.text, True)
        self.tvcolumn1.pack_start(self.toggle, True)

        self.tvcolumn0.add_attribute(self.text, 'text', 0)
        self.tvcolumn1.set_cell_data_func(self.toggle, self.set_status)

        self.window.add(self.treeview)

        self.window.show_all()

def main():
    gtk.main()

if __name__ == "__main__":
    tvexample = BasicTreeViewExample()
    main()

【讨论】:

  • 鉴于您的解释和文档,这应该是要做的事情,但我不知道如何只更改一行。当我在函数内部并更改 CellRendererToggle 的属性时,它会影响每一行的每个框......我稍后会继续尝试(我会在我的问题中提供详细信息)。
  • 见上文,我添加了一个示例,该示例根据给定文本设置切换状态,该文本为“不一致”或“一致”。
  • 你说得对,我明白了! «重点是始终为每个单元格设置单元格属性。»谢谢 !另外,您让我发现我们可以更改单元格的性质(文本或按钮),我将使用它。
【解决方案2】:

我最近遇到了同样的问题,发现如果您希望直接从模型中的列设置属性,则不需要单元格数据函数。问题的代码中需要的更新应该如下:

self.treeModel = Gtk.TreeStore(str, bool, bool)
...
column_toggle = Gtk.TreeViewColumn("Installer", renderer_toggle, active=1, inconsistent=2)

然后根据需要在新列中设置不一致的值。

作为关于何时在模型中选择单元数据函数或新列的提示,请考虑以下因素 (Gtk+ By Example):

每次渲染该(渲染器)列中的单元格时,都会调用您的单元格数据函数。如果你曾经使用过这个函数,去检查一下这个函数在你的程序中被调用的频率。如果您在单元格数据函数中执行耗时的操作,事情不会很快,尤其是当您有很多行时。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多