如何在移动子树后更新TreeModel

时间:2011-09-06 07:43:02

标签: python pygtk gtktreeview

我有一个自定义的GenericTreeModel,工作得很好。现在我希望用户能够使用拖放重新排列节点,因此我将节点移动到数据模型中的新父节点。 然而,TreeModel希望使用row_has_child_toggledrow_deletedrow_inserted等方法接收通知。

显然没有row_moved并且调用row_deleted(对于原始路径)而row_inserted(对于新路径)似乎还不够。所以我想我可能不得不递归地发出这些变化。

考虑以下示例:

* A (0,)
* B (1,)
  * C (1,0)
    * D (1,0,0)

现在,如果我将C移到A,会发生以下情况:

row_delete( (1,0) ) # C
row_delete( (1,0,0) ) # D
row_inserted( (0,0) ) # C'
row_inserted( (0,0,0) ) # D'
child_toggle( (0,) ) # A
child_toggle( (1,) ) # B
child_toggle( (0,1) ) # C'

然而,gtk仍然抱怨模型的状态不一致。我想到了两件事:

  • 也许调用这些函数的顺序是相关的(如果有任何想法如何?)
  • 技术上child_toggle( (1,0) )也会发生,但是行已经a)已经删除了b)row_has_child_toggled需要tree_iter引用,这是我无法获得的,因为它不存在任何更多。

也许我在这里采取了一种完全错误的方法,那么最好的方法是什么呢?

2 个答案:

答案 0 :(得分:2)

想出来:通过删除子树的根节点行(通知模型路径已经消失并有条件地切换parent.has_child),删除子树可以正常工作。插入新子树同样如此,所以我不需要递归地告诉模型。

然而,这种组合至关重要,所以

  1. 首先删除,通知模型
  2. 然后再次插入并通知模型。

答案 1 :(得分:1)

恕我直言,如果您使用“drag_data_get”和“drag_data_received”方法正确连接树视图,则此更新应自动进行树视图,并允许其作为源和目标及其“enable_model_drag_dest”和“enable_model_drag_source”方法。 树视图应该没什么可做的。

模型必须在对其“drag_data_received_data”的调用中更新,但没有“删除”要做,只有特定的“insert_before”或“insert_after”如下所示:

   def drag_data_received_data(self, treeview, context, x, y, selection,
                               info, etime):
       model = treeview.get_model()
       data = selection.data
       drop_info = treeview.get_dest_row_at_pos(x, y)
       if drop_info:
           path, position = drop_info
           iter = model.get_iter(path)
           if (position == gtk.TREE_VIEW_DROP_BEFORE
               or position == gtk.TREE_VIEW_DROP_INTO_OR_BEFORE):
               model.insert_before(iter, [data])
           else:
               model.insert_after(iter, [data])
       else:
           model.append([data])
       if context.action == gtk.gdk.ACTION_MOVE:
           context.finish(True, True, etime)
       return

此代码段来自:

http://www.pygtk.org/pygtk2tutorial/sec-TreeViewDragAndDrop.html#DragDropReordering

程序“treeviewdnd.py”可以完美地显示您需要的内容。

希望这能解决你的任务!