2014-01-29 51 views
0

我實現了一個自定義的TreeModel在PyGI(GTK3)以下方式(如建議herehere):GTK3中的TreeModel(PyGI)第一次調用do_iter_next(iter)?

test.py

from gi.repository import Gtk 

class Store(GObject.Object, Gtk.TreeModel): 
    def __init__(self): 
     self.data = [[i*j for i in range(10)] for j in range(10)] #multiplication table 
     super(Store, self).__init__() 

    #boilerplate TreeModel interface implementation 
    def do_get_flags(self): 
     print "do_get_flags called" 
     return Gtk.TreeModelFlags.LIST_ONLY 

    def do_get_n_columns(self): 
     print "do_get_n_columns called" 
     return len(self.data[0]) 

    def do_get_column_type(self, index): 
     print "do_get_column_type called; index = %s"%(index) 
     if index < 10: 
      return str 
     else: 
      raise IndexError 

    def do_get_iter(self, path): 
     print "do_get_iter called; path = %s"%(path) 
     indices = path.get_indices() 
     if indices[0] < len(self.alignment.sequences): 
      iterator = Gtk.TreeIter() 
      iterator.user_data = indices[0] 
      print "iterator.user_data = %s, iterator = %s" % (iterator.user_data, iterator) 
      return (True, iterator) 
     else: 
      return (False, None) 

    def do_get_path(self, iterator): 
     print "do_get_path called; iter = %s" % (iter) 
     if iterator.user_data is not None: 
      path = Gtk.TreePath(iterator.user_data) 
      return path 
     else: 
      return None 

    def do_get_value(self, iterator, column_index): 
     print "do_get_value called; iterator = %s, column_index = %s"%(iterator, column_index) 
     item = self.data[iterator.user_data][column_index] 

    def do_iter_next(self, iterator): 
     print "do_iter_next_called; iterator = %s"%(iterator) 
     #returns next iterator 
     if not hasattr(iterator, "user_data"): 
      print self.do_get_path(iterator) 
      return 
     else: 
      print "user data = %s" % (iterator.user_data) 
     try: 
      return self.do_get_iter(Gtk.TreePath((iterator.user_data+1,))) 
     except IndexError: 
      return None 

    def do_iter_has_child(self, iterator): 
     print "do_iter_has_child called; rowref = %s" % (iterator) 
     return False 

    def do_iter_nth_child(self, iterator, index): 
     print "do_iter_nth_child called; iterator = %s, index = %s" % (iterator, index) 
     output_iterator = Gtk.TreeIter() 
     output_iterator.user_data = index 
     return (True, output_iterator) 

    def do_iter_parent(self, child): 
     print "do_iter_parent called; child = %s" % (child) 
     return None 


def main(): 
    model = Store() 
    view = Gtk.TreeView(model) 

    for index, column in enumerate(alignment): 
     renderer = Gtk.CellRendererText() 
     column = Gtk.TreeViewColumn(str(index)) 
     column.pack_start(renderer, False) 
     column.add_attribute(renderer, "markup", index) 
     #column.props.sizing = Gtk.TreeViewColumnSizing.FIXED 
     view.append_column(column) 

    scrolled = Gtk.ScrolledWindow() 
    scrolled.add(view) 

    window = Gtk.Window(title="title") 
    window.set_size_request(480, 640) 
    window.add(scrolled) 
    window.show_all() 
    return window 


if __name__ == "__main__": 
    window = main() 
    window.connect('destroy', Gtk.main_quit) 
    Gtk.main() 

可惜,這實現不工作,由於瘋狂的行爲do_iter_next()。看看日誌文件的內容,創建由python test.py &> test.log

test.log中

do_get_n_columns called 
do_get_column_type called; index = 0 
do_get_flags called 
do_get_iter called; path = 0 
iterator.user_data = 0, iterator = <GtkTreeIter at 0x8797cb0> 
do_iter_next_called; iterator = <GtkTreeIter at 0xbfb243c0> 
user data = None 
Traceback (most recent call last): 
    File "minimal_example.py", line 65, in do_iter_next 
    return self.do_get_iter(Gtk.TreePath((iterator.user_data+1,))) 
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int' 
do_iter_next_called; iterator = <GtkTreeIter at 0xbfb243c0> 
user data = None 
Traceback (most recent call last): 
    File "minimal_example.py", line 65, in do_iter_next 
    return self.do_get_iter(Gtk.TreePath((iterator.user_data+1,))) 
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int' 
do_iter_next_called; iterator = <GtkTreeIter at 0xbfb243c0> 
user data = None 

你想過爲什麼第一do_get_iter()返回一個迭代器,然後do_iter_next(任何想法)發生在輸入另一個一個是空的user_data。另外,你是否明白,是否user_data是由GTK3作者分配的特定領域?參考手冊沒有提到它,但爲什麼然後它出現在0xbfb243c0我的神祕iter?

回答

1

Gtk.TreeIters.user_data的用法正常。在3.8版之前的pygobject的版本中,有一些歷史包袱與內存泄漏(但仍然有效)有關。 pygobject 3.8將字段更改爲只允許整數值並修復泄漏。但是,3.8.0和3.8.1版本在訪問時會繼續將整數值0解釋爲None,這是您所看到的問題。版本3.8.2及以上版本修正了這個問題,因此訪問時返​​回值爲0。

要之前3.8.2支持pygobject版本,你可以寫一個訪問函數來獲取用戶的數據:

def get_user_data(tree_iter): 
    if tree_iter.user_data is None: 
     return 0 
    return tree_iter.user_data 

參見:https://bugzilla.gnome.org/show_bug.cgi?id=698366

相關問題