简体   繁体   中英

How to retain the selection when updating a PyGTK combobox?

This is a follow-up to a question I asked yesterday. What I want to do is to get a set of PyGTK-comboboxes to get updated whenever a value is selected in one of them. Initially they all contain the same items to choose from, but when a value is selected this value should no longer be available in any of the other comboboxes (unless it's present as a duplicate in the original list).

I have got as far as creating a list of the values which should be available for a particular combobox, and he who answered yesterday's question also kindly provided me with a way of listing all currently existing items in the box, so I now compare the 'should be available' list to the 'currently available list' and only set out to update a combobox if those two lists differ. Everything works well - apart from the fact that whenever I remove the old contents from a combobox all current selections vanish, and my attempts to re-establish the selection have just led to infinite mutual combobox-updating.

I have conducted several searches, but none of the methods I found have worked for me, so again I'm at my wit's end, thus it would be great if someone could help me out. Here's the current version of the code I'm using:

# 'combo_list' contains all the comboboxes of interest
# 'indx_in_combo_list' is the index (from 'combo_list') of the combobox which
# triggered the updating process

def changed_single_score(self, source_combo, all_scores, combo_list, indx_in_combo_list):
    # append '0' so that swapping values remains possible
    available_items = all_scores.split(', ') + ['0']

    for i in range(len(combo_list)):
        # make items unavailable that are selected in one of the boxes
        selected = self.get_active_text(combo_list[i])
        if selected in available_items:
            available_items.remove(selected)

    for indx in range(len(combo_list)):
        # don't try changing the combobox which triggered updating
        if indx != indx_in_combo_list:
            existing_items = [model_item[0] for model_item in combo_list[indx].get_model()]
            local_selection = self.get_active_text(combo_list[indx])
            local_available = available_items[:]

            # each box must retain its own selected item
            if local_selection != None:
               local_available.append(local_selection)

            local_available.sort()
            local_available.reverse()
            existing_items.sort()
            existing_items.reverse()

            if existing_items != local_available:

                # if I uncomment the following line the boxes are cleared
                # but all selections vanish, too
                #combo_list[indx].get_model().clear()

                for item in local_available:
                    combo_list[indx].append_text(item)

                # I want to make sure that the selection is retained,
                # but if I do it like this I just cause emission of the
                # 'changed' signal, thus I get infinite recursion again
                #if local_selection != None:
                #    combo_list[indx].set_active(local_available.index(local_selection))

The above function is called in the following context:

combo_list[indx].connect('changed', self.changed_single_score, self.selected['scores'], combo_list, indx)

I also tried deleting all old entries one by one and just keeping the one with the selection, but that didn't work either. I'm probably overlooking the obvious solution again, but if someone here could point it out to me that would be great!

Thanks a lot in advance.

You could lock the code with a boolean in the top of your function from being executed by the additional signals that will call it while you fill the combo boxes.

if self.changed_single_score_locked:
    return
else:
    self.changed_single_score_locked = True
  1. store what was selected
  2. clear box
  3. repopulate
  4. select what was selected

Then remove the lock at the end of the function:

self.changed_single_score_locked = False

Or maybe shut down the signal completely by some other means using the GTK API?

Edit: Use handler_block instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM