2013-02-07 48 views
4

在Gtk + 3上,我使用TreeModel來存儲嵌套信息,並使用CellRendererTextCellRendererToggle來顯示它。用戶可以在每個切換按鈕上點擊,當有嵌套的時候,他們不在同一狀態,我想讓上層的人反映「不一致」狀態。我如何設置這個屬性爲單元將CellRendererToggle的單行設置爲不一致

爲了更清楚,什麼我想從傳輸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(我用的,而不是一個listStore一個treeStore)

這是我的代碼:

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

謝謝!

編輯:回答馬庫斯:我不出來,當我改變裏面的功能我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. 

我必須再試一次。 我想知道...我們是否真的必須手動執行它,難道它不是樹視圖中的一個功能嗎?

+1

我已經添加了一些示例代碼(我是一個Python dilettante,但我希望它顯示了這一點)。如果第一個文本列的值爲「不一致」,則切換列也會設置爲不一致。如果第一列的文本值爲「一致」,則切換列設置爲「正常」狀態(根本不切換)。 –

回答

4

可以通過使用單元格數據函數來設置一個元素的屬性。因爲我只用C語言完成了這個工作,所以我只能傳給你PyGTK文檔的鏈接,我還沒有看到PyGObject的這個特性的相關文檔。

對於PyGTK是被記錄在案herethis頁面提供了底部爲例,使用了單元格數據功能的PyGTK還發表在this文件。

例如,如果你想要做的一樣傳輸,你可以做到以下幾點: 既然你收到當前國際熱核實驗堆的電池數據函數的參數,你可以通過它所有的孩子存在循環,檢查孩子的狀態。然後你會知道在父節點上設置哪個狀態。現在的重點是在單元格數據函數中設置一個屬性只會影響這個單元格,而不會影響樹視圖的所有元素。

我可以給你也是一個視覺例子爲我自己的應用程序:

enter image description here

我在這個樹狀柱「值」。如果「Menu Element」列中的值設置爲「enabled」,並且「Type」列中的值爲「option」,則顯示一個複選框而不是文本(我突出顯示了這樣一行)。示例圖像還顯示一個激活搜索,其中突出顯示搜索結果。這兩種方法都可以通過單元格數據函數來設置一個元素的屬性,就像您在問題中所要求的那樣。

編輯

我已經做了一些示例代碼。重點是單元格屬性總是爲每個單元格設置。因此,不僅僅是「如果...,然後設置屬性」,而是「如果,設置像這樣的屬性,否則,設置屬性」。 (它基於舊的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() 
+0

鑑於你的解釋和文檔,這應該是要做的事情,但我無法弄清楚如何只改變一行。當我在函數內部時,我改變了CellRendererToggle的屬性,它會影響每一行的每一行...我稍後繼續嘗試(我在我的問題中提供了詳細信息)。 – Ehvince

+0

參見上面,我添加了一個例子,它根據給定文本設置切換狀態,該文本可以是「不一致」或「一致」。 –

+0

你說得對,我明白了! «重點是單元格屬性總是爲每個單元格設置»謝謝!另外,你讓我發現我們可以改變單元格的本質(文本或按鈕),我將使用它。 – Ehvince

1

我最近有同樣的問題,發現如果您希望直接從模型中的列設置屬性,則不需要單元格數據函數。這將做到這一點應爲從問題中的代碼所需要的更新:

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

,然後根據需要在新的列設置不一致值。

其何時選擇單元格數據功能或模型中的新列的暗示,採取以下考慮(Gtk+ By Example):

你的電池數據功能將被稱爲每一次該(渲染器)列中的單元格即將呈現。如果您曾經使用過,請檢查程序中調用此函數的頻率。如果您在單元格數據函數中執行耗時的操作,則事情不會很快,尤其是如果您有很多行時。