Recently I’ve had the pleasure to play around with GTK from Python while working on a (by now not so) little app for KanColle. (Since that last update on github I’ve rewritten the whole thing from scratch, but that’s not the point now.) On the way, I encountered a quite annoying problem: the reorder_child method for gtk.Menu just doesn’t work. I use Python 2.7, gtk.gtk_version says that’s 2.24.20, and gtk.pygtk_version is 2.24.0.
What I do: I have all the Menu’s elements (all instances of a class derived from gtk.MenuItem) stored in a dictionary so that I can easily identify and update them. The number and identity of these elements are fixed, but the order they are spawned is not. Eg. it’s perfectly possible that the element that’s supposed to be at the top of the menu is added last. Or second. Or fourth.
At first I used gtk.Menu’s append method to just add the elements as they spawned, and afterwards I intended to reorder them using reorder_child. However, it didn’t work. At all. I asked a professional programmer for help, and after some thorough debugging we still got the same result: reorder_child just doesn’t work.
All the elements are added, updated, modified and displayed properly. It was just their order that was amiss.
So I came up with an alternative. Since I already had a list of the elements ids sorted, I reversed that into a dictionary in the form of {‘id’: position, ‘id’:position,…}. Then instead of using Menu.append, I used Menu.insert, with which I can specify at what position the new element should be inserted.
This could still be quite risky, but luckily if the position in question is already taken (which is possible, since if you insert something at position 4 when the Menu is still empty, it’s gonna be added at position 0), then the old elements are pushed down as the new takes their place. This was the best I could come up with, and for now it works.
After a while sadly, the method I described above started breaking. However, under the pressure of this unfixable “bug” I just picked a radical method. I preloaded the Menu with (empty) items, then later once I got the data to display I just updated their labels and made them visible with show(). This is a really “convenient” way to handle the matter if you know at most how many elements there will be in the Menu.