python - 将 CellRendererToggle 的单行设置为不一致

标签 python gtk gtk3

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

为了更清楚,我想从 Transmission bittorrent 客户端实现的示例: enter image description here

我知道如何使用 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 的一个开箱即用的功能吗?

最佳答案

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

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

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

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

enter image description here

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

编辑

我已经完成了一些示例代码。要点是始终为每个单元格设置单元格属性。因此,不仅仅是“如果...,则设置属性”,而是“如果,像这样设置属性,否则,像那样设置属性”。 (它基于旧的 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()

关于python - 将 CellRendererToggle 的单行设置为不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14761389/

相关文章:

haskell - 使用 Reflex.GI.Gtk,如何在事件中使用和强制评估动态

python - 如何在Python中使用youtube dl获取youtube视频url

python - u'string' 和 unicode(string) 的区别

c - 为什么行不通过调用 gtk_list_store_set 函数在 TreeView 中更新

c++ - 不使用设置颜色的开罗渐变图案

linux - 对符号 'gdk_pixbuf_major_version' 的 undefined reference

python - 类型错误 : data type not understood while parsing CSV with Pandas

Python 多核 CSV 短程序,需要建议/帮助

c++ - 在 32 位 Linux 上编译代码时出现未声明错误 'gtk_window_set_keep_above'

c - 如何在 gtk3 中获得事件的 gtk 窗口?