У меня есть ListStore в PyGTK, у которого есть куча строк. Существует фоновое задание, обрабатывающее данные, представленные строками, и когда он заканчивается, ему необходимо обновить строку. Конечно, для этого нужно знать, какую строку обновить, и, таким образом, сохранить итератор в строке вокруг. Тем не менее, во время жизненного цикла фона пользователь может удалить строку. Это нормально - мы просто заменяем сохраненный итератор "None", и фоновая работа продолжается весело. Проблема в том, что при удалении строки итераторы не сравниваются как равные, и ничто не становится равным None. На самом деле, нет двух итераторов AFAIK, сравните их. Проблема в минимальном примере такова:
>>> store = gtk.ListStore(int)
>>> store.insert(1)
<GtkTreeIter at 0x1d49600>
>>> print store[0].iter == store[0].iter
False
Ложь, но они же итератор! (Я знаю, что они разные экземпляры, но они представляют одно и то же, и они определяют метод __eq__
.) Что мне здесь не хватает и как отслеживать строки в ListStore для последующего обновления?
Я бы подошел к этому по-другому - вот что я сделал в подобной ситуации:
GObject
GObject
есть куча свойствnotify::myproperty
В то же время:
ListStore
хранит эти объекты и использует метод gtk.TreeViewColumn.set_cell_data_func()
для отображения каждого столбца (см. примечание ниже).TreeView
, подключается к notify::myproperty
notify::...
, вызывает сигнал row-changed
на ListStore
Некоторые коды:
def on_myprop_changed(self, iter, prop):
path = self.model.get_path(iter)
self.model.row_changed(path ,iter)
def on_thing_processed(self, thingdata):
# Model is a ListStore
tree_iter = self.model.append((thingdata,))
# You might want to connect to many 'notify::...' signals here,
# or even have your underlying object emit a single signal when
# anything is updated.
hid = thingdata.connect_object('notify::myprop',
self.on_myprop_changed,
tree_iter)
self.hids.add((thingdata, hid))
Я сохраняю скрытые объекты в списке, чтобы я мог отключить их, когда таблица очищена. Если вы позволите удалить отдельные строки, вам, вероятно, потребуется сохранить их на карте (путь → скрыть, или объект → скрыть).
Примечание. Необходимо помнить, что set_cell_data_func
заставляет строку повторно проверять свою информацию каждый раз при перерисовке, поэтому базовая функция должна быть просто функцией поиска, а не интенсивным вычислением. Практически говоря, из-за этого вы можете уйти от того, чтобы не выполнять процедуру "подключение к сигналу/испусканию строки", но лично я чувствую себя лучше, зная, что не будет никаких случаев с краями.
Попробуйте использовать метод хранения списка .get_path(iter)
и сравните результирующие пути вместо сравнения итераторов напрямую.
UPDATE: вы можете просто вызвать set_value
с недопустимым iter
. gtk
предоставит вам предупреждение, но не исключит ничего. Вероятно, он просто проверяет, действительно ли он действительный итер.