How to stop infinite recursion when Python objects trigger each other's updates?
I'm using PyGTK and the gtk.Assistant widget. On one page I have six comboboxes, which initially have the same contents (six numbers). When the users selects a number in one of those comboboxes, this number should no longer be available in the other开发者_JAVA百科 five boxes (unless it's present as a duplicate in the original list). Hence I would like to always update the contents.
I have tried the following approach (just a few code snippets here), but (of course...) it just jumps into infinite recursion once the process has been triggered:
# 'combo_list' is a list containing the six comboboxes
def changed_single_score(self, source_combo, all_scores, combo_list, indx_in_combo_list):
scores = all_scores.split(', ')
for i in range(6):
selected = self.get_active_text(combo_list[i])
if selected in scores:
scores.remove(selected)
# 'scores' only contains the items that are still available
for indx in range(6):
# don't change the box which triggered the update
if not indx == indx_in_combo_list:
# the idea is to clear each list and then repopulate it with the
# remaining available items
combo_list[indx].get_model().clear()
for item in scores:
combo_list[indx].append_text(item)
# '0' is appended so that swapping values is still possible
combo_list[indx].append_text('0')
The above function is called when a change occurs in one of the comboboxes:
for indx in range(6):
for score in self.selected['scores'].split(', '):
combo_list[indx].append_text(score)
combo_list[indx].connect('changed', self.changed_single_score, self.selected['scores'], combo_list, indx)
Perhaps I ought to mention that I'm new to Python, OOP, and also rather new to GUI-programming. I'm probably being really stupid here, and/or overlooking the obvious solution, but I have so far been unable to figure out how to stop each box from triggering updating of all other boxes once it itself has been updated.
Thanks in advance for your replies - any help would be greatly appreciated.
The simplest fix for this sort of problem is generally to figure out if you're going to need to change the contents of the object (the combobox, in your case) and then only apply changes if you're actually changing something. This way you'll only propagate update events as far as they do something.
This should look something like:
# '0' is appended so that swapping values is still possible
items = [item for item in scores] + ['0']
for indx in range(6):
# don't change the box which triggered the update
if not indx == indx_in_combo_list:
# I'm not 100% sure that this next line is correct, but it should be close
existing_values = [model_item[0] for model_item in combolist[indx].get_model()]
if existing_values != items:
# the idea is to clear each list and then repopulate it with the
# remaining available items
combo_list[indx].get_model().clear()
for item in items:
combo_list[indx].append_text(item)
This is a pretty general approach (even some build systems use it). The main requirement is that things actually do settle. In your case it should settle immediately.
精彩评论