将CellRendererToggle的单行设置为不一致 [英] Setting a single row of a CellRendererToggle to inconsistent

查看:102
本文介绍了将CellRendererToggle的单行设置为不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Gtk + 3上,我使用 TreeModel 来存储嵌套信息,并使用 CellRendererText CellRendererToggle 。用户可以在每个切换按钮上点击,当有嵌套的时候,他们不在同一状态,我想让上层的人反映不一致状态。如何为 一个元素 设置此属性?



为了更清晰起见,我想要的一个示例实现从传输bittorrent客户端:

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



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



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



这是我的代码:

  class HelloMyApp:

def __init __(self):

设置Glade文件
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)

########这是我的模型:它存储一个字符串和一个布尔值。 #########
self.treeModel = Gtk.TreeStore(str,bool)

#有关如何在模型中插入数据的示例
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 two',True])


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

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

#使用文本和另一列的切换按钮
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn(Title,renderer,text = 0)
treeview1.append_column(column)

######这里是CellRendereToggle ################
renderer_toggle = Gtk.CellRendererToggle()
renderer_toggle。连接(切换d,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):
如果'cat'在treeModel.get_value (treeIter,0):
#它只发生在我的模型中,
#所以在这里我是连续的,我想改变为不一致。
cellRenderer.set_property('inconsistent',True)
#我期待这改变了那一行的方框,但它会影响每一行。

else:
cellRenderer.set_property('inconsistent',False)#现在没关系。

我必须再试一次。
我想知道...我们是否真的必须手动执行它,不能将它作为treeView的一个功能吗?

解决方案

可以通过使用单元格数据函数来设置一个元素的属性。因为我只用C语言完成了这个工作,所以我只能传给你PyGTK文档的链接,我还没有看到PyGObject的这个特性的相关文档。



PyGTK被记录在这里 页面为您提供了一个示例,PyGTK的单元格数据函数的使用也在这个文档。



例如,如果您想要在Transmission中执行相同的操作,您可以执行以下操作:
由于您将当前iter作为单元格数据函数的参数接收,因此您可以遍历其中的所有子节点并检查chi的状态ldren。然后你会知道在父节点上设置哪个状态。现在的重点是在单元格数据函数中设置一个属性只会影响这个单元格,而不是所有treeview元素。



我也可以给你一个视觉例子为我自己的应用程序:





我在这个树视图中有Value列。如果Menu Element列中的值设置为enabled,并且Type列中的值为option,则显示一个复选框而不是文本(我突出显示了这样一行)。示例图像还显示一个激活搜索,其中突出显示搜索结果。您可以使用单元格数据函数来设置一个元素的属性,如您在问题中所要求的。



我已经做了一些示例代码。重点是单元格属性总是为每个单元格设置。因此,不仅仅是如果...,然后设置属性,而是如果,设置像这样的属性,否则,设置属性。 (它基于旧的PyGTK文档,但它应该澄清事情)。

 #!/ usr / bin / env python 

#例子basictreeview.py

导入pygtk
pygtk.require('2.0')
导入gtk

类BasicTreeViewExample:
$ b $ def set_status(self,column,cell,model,iter):
如果model.get_value(iter,0)中的'inconsistent':
cell.set_property( '不一致',真)
else:
cell.set_property('inconsistent',False)
返回

def delete_event(self,widget,event,data =无):
gtk.main_quit()
返回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)

适用于父级范围(4):
piter = self.treestore.append(无,['parent%i'%parent])
范围内的孩子(3):
如果孩子== 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。文本,真)
self.tvcolumn1.pack_start(self.toggle,True)

self.tvcolumn0.add_at tribute(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()


On Gtk+3, I'm using a TreeModel to store nested information and I display it with a CellRendererText and a CellRendererToggle. The user can clic on every toggle button, and when there are nested ones and they are not in the same state, I want the ones of upper level to reflect the 'inconsistent' state. How can I set this property for one element ?

For more clarity, an example of what I want to achieve from the Transmission bittorrent client :

I know how to set all the buttons of the cell renderer to the inconsistent state with myCellRendererToggle.set_properties(inconsistent=True) but it seems I can't access one single element from here;

I know how to access a particular row of my TreeStore model, but I can only set «True» and «False» values.

My code is fairly close to the official documentation so you can help me with it : https://python-gtk-3-tutorial.readthedocs.org/en/latest/cellrenderers.html#cellrenderertoggle (I use a treeStore instead of a listStore)

And this is my code :

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()

Thanks !

edit : to answer Marcus : I can't figure it out, when I change the property of my CellRendererToggle inside the function, it changes every row.

edit for the solution : as Marcu pointed out, we have to set the property in every case, that's why I added the else part.

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.

I have to try again. I wonder… do we really have to do it manually, can't it be a feature out of the box of the treeView ?

解决方案

It is possible to set the property of one element via using a cell data function. Since I have done this only in C yet, I can only pass you the link to the documentation of PyGTK, I haven't seen the relevant docs for this feature for PyGObject yet.

For PyGTK is was documented here, this page gives you an example at the bottom, the use for cell data functions for PyGTK was also featured in this document.

If for example you would like to do the same as in Transmission, you could do the following: Since you receive the current iter as a parameter of the cell data function, you could loop through all of its children there and check the status of the children. You would then know which state to set at the parent node. Now the main point is that setting a property inside the cell data function will affect only this single cell, and not all elements of the treeview.

I can give you also a visual example for my own application:

I have the column "Value" in this treeview. If the value inside the column "Menu Element" is set to "enabled" and the value inside the column "Type" is "option", a checkbox is shown instead of text (I have highlighted such a row). The example image also shows an active search, which highlights search results. Both is possible with a cell data function to set the property of one element as you asked for in your question.

Edit

I've done some example code. The main point is that the cell property is always set for every cell. So not just "if ..., then set property" but "if, set property like this, else, set property like that". (It's based on the old PyGTK documentation, but it should clarify things anyway).

#!/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的单行设置为不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆