pygtk GtkTreeIter 比较
我在 PyGTK 中有一个 ListStore,其中有很多行。有一个后台作业正在处理行所表示的数据,当它完成时,它需要更新该行。当然,要做到这一点,它需要知道要更新哪一行,从而保持该行的迭代器。但是,在后台作业生命周期中,用户可能会删除该行。这没关系——我们只需将存储的迭代器替换为“None”,后台作业就可以愉快地继续进行。问题是,当删除该行时,迭代器比较不相等,并且没有任何内容设置为 None。事实上,据我所知,没有两个迭代器比较相等。在一个最小的例子中,问题是这样的:
>>> store = gtk.ListStore(int)
>>> store.insert(1)
<GtkTreeIter at 0x1d49600>
>>> print store[0].iter == store[0].iter
False
错误,但它们是相同的迭代器! (我知道它们是不同的实例,但它们代表相同的事物,并且它们定义了一个 __eq__ 方法。)我在这里缺少什么,以及如何跟踪 ListStore 中的行以后更新?
I have a ListStore in PyGTK, which has a bunch of rows. There is a background job processing the data represented by the rows, and when it finishes, it needs to update the row. Of course, to do this, it needs to know which row to update, and is thus keeping an iterator to the row around. However, during the background jobs life, the user might remove the row. This is OK — we just replace the stored iterator with "None", and the background job continues along merrily. The problem is that when the row is removed, the iterators don't compare as equal, and nothing gets set to None. In fact, no two iterators, AFAIK, compare equal. The problem, in a minimal example, is this:
>>> store = gtk.ListStore(int)
>>> store.insert(1)
<GtkTreeIter at 0x1d49600>
>>> print store[0].iter == store[0].iter
False
False, yet they're the same iterator! (I'm aware they are different instances, but they represent the same thing, and they define a __eq__
method.) What am I missing here, and how do I keep track of rows in a ListStore for later updating?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
尝试使用列表存储的
.get_path(iter)
方法,并比较结果路径,而不是直接比较迭代器。更新:您只需使用无效的
iter
调用set_value
即可。gtk
会给你一个警告,但不会抛出异常或任何东西。它可能只是检查它是否是一个有效的 iter。Try using the list store's
.get_path(iter)
method, and compare the resulting paths, instead of comparing the iterators directly.UPDATE: You can just call
set_value
with the invaliditer
.gtk
will give you a warning but will not throw an exception or anything. It probably just checks whether it's a valid iter anyway.我会以不同的方式处理这个问题 - 这是我在类似情况下所做的:
GObject
的实例GObject
子类有一个一堆属性notify::myproperty
信号同时:
ListStore
存储这些对象,并使用gtk.TreeViewColumn .set_cell_data_func()
方法渲染每列(参见下面的注释)TreeView
的对象连接到notify::myproperty
notify::...
信号的函数会触发ListStore
上的row-changed
信号一些代码:
我将 hids 保留在一个列表,以便我可以在表格被清除时断开它们的连接。如果您让个别行被删除,您可能需要将它们存储在地图中(路径 -> hid,或对象 -> hid)。
注意:您需要记住,
set_cell_data_func
会导致该行在每次重绘时重新检查其信息,因此底层函数应该只是一个查找函数,而不是一个密集计算。实际上,因此您可以不执行“连接到信号/发出行更改”过程,但我个人感觉更好,因为知道不会有任何边缘情况。I would approach this differently — here's what I've done in a similar situation:
GObject
GObject
subclass has a bunch of propertiesnotify::myproperty
signalAt the same time:
ListStore
stores these objects, and uses thegtk.TreeViewColumn.set_cell_data_func()
method to render each column (see note below)TreeView
connects to thenotify::myproperty
notify::...
signal triggers therow-changed
signal on theListStore
Some code:
I keep the hids in a list so I can disconnect them when the table is cleared. If you let individual rows get removed, you'll probably need to store them in a map (path -> hid, or object -> hid).
Note: You need to remember that
set_cell_data_func
causes the row to re-check its information every time there's a redraw, so the underlying function should just be a lookup function, not an intensive computation. Practically speaking, because of this you could get away with not doing the "connect-to-signal/emit-row-changed" procedure, but personally I feel better knowing that there won't be any edge cases.