Discussion:
problem with dynamic popup menu when ids get too large?
raf
2014-10-08 04:33:39 UTC
Permalink
Hi,

windows-8.1, python-2.7.8, wxpython-2.8.12.1

I have an application with a large dynamic popup menu.
Every time I construct it, I use ID_ANY as the id
for all the menu items.

After calling frame.PopupMenu(menu), I call menu.Delete()
but all of the ids used in the menu remain effectively
claimed and the next time the menu is constructed,
the ids used by the new menu items are higher than the
last time.

I assume that's ok because http://wiki.wxpython.org/Getting%20Started
says "You can make your own IDs, but there is no reason to do that."

However, occasionally I get reports from the users that when they
select a menu item, the application behaves as though some other
completely unrelated menu item had been selected.

I added some logging to see what was going on and asked them to
tell me when it next happened which it just has. It seems that the
problem happened the first time the user selected an item
after the menu item ids has exceeded 2**16. This might be an
unimportant coincidence. I only have one data point. But it
might be relevant.

When the problem occurs, the id of the selected menu item is a
much lower number than the ids of any of the menu items that
exist in the menu at the time. It looks as though it's using
a much earlier id from a previous incarnation of the menu.

Does anyone have any idea what might be going wrong?

If it could have something to do with the ever increasing ids,
is there a way to tell wx to reset its next-available-id to
be one more than the currently used id?

Would using application-defined ids be ok or might other uses
of ID_ANY reuse ids that I've chosen?

Cheers,
raf
--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Nathan McCorkle
2014-10-08 18:30:11 UTC
Permalink
Are you destroying the menu object after popping it up?
--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
raf
2014-10-13 21:28:40 UTC
Permalink
Post by Nathan McCorkle
Are you destroying the menu object after popping it up?
yes. i said so in my original mail.

any other ideas?

cheers,
raf
--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Robin Dunn
2014-10-14 00:11:13 UTC
Permalink
Post by raf
Hi,
windows-8.1, python-2.7.8, wxpython-2.8.12.1
I have an application with a large dynamic popup menu.
Every time I construct it, I use ID_ANY as the id
for all the menu items.
After calling frame.PopupMenu(menu), I call menu.Delete()
but all of the ids used in the menu remain effectively
claimed and the next time the menu is constructed,
the ids used by the new menu items are higher than the
last time.
I assume that's ok because http://wiki.wxpython.org/Getting%20Started
says "You can make your own IDs, but there is no reason to do that."
However, occasionally I get reports from the users that when they
select a menu item, the application behaves as though some other
completely unrelated menu item had been selected.
I added some logging to see what was going on and asked them to
tell me when it next happened which it just has. It seems that the
problem happened the first time the user selected an item
after the menu item ids has exceeded 2**16. This might be an
unimportant coincidence. I only have one data point. But it
might be relevant.
It is. IIRC, Windows has a limit for menu IDs but a different limit for
control IDs. In 2.8 and prior[1] the IDs generated for wx.ID_ANY (and
those returned from wx.NewId()) are basically just an incrementing
global variable with almost no smarts behind it. There is also
wx.RegisterId(val) which will bump the auto-increment sequence to val+1
so you can reserve some IDs that way if you want, but you can still run
into issues if the value wraps around and comes back to IDs that you may
still be using somewhere. And then there are problems when the ID passes
some artificial limit that the platform imposes.
Post by raf
When the problem occurs, the id of the selected menu item is a
much lower number than the ids of any of the menu items that
exist in the menu at the time. It looks as though it's using
a much earlier id from a previous incarnation of the menu.
Does anyone have any idea what might be going wrong?
If it could have something to do with the ever increasing ids,
is there a way to tell wx to reset its next-available-id to
be one more than the currently used id?
Would using application-defined ids be ok or might other uses
of ID_ANY reuse ids that I've chosen?
What I've tended to do in situations like this where there will be lots
of items needing IDs being created, is to go ahead and use fixed ID
values for the items, but use wx.NewId() to give me the ID values. That
way they won't conflict with any other IDs that are still being
generated with wx.ID_ANY (as long as they don't wrap around, but then
that is what you are trying to prevent by doing this) and they will also
not conflict with any stock IDs. For example, I'll have globals like this:

MY_ID_1 = wx.NewId()
MY_ID_2 = wx.NewId()
etc.

and then use those IDs where I create the popup menus. Presetting your
menu IDs like that also means that you don't need to Bind/Unbind the
event handlers each time you popup the menu, just do it once at the
beginning of the program.


[1] There was a change made in the 2.9 series that puts some more
intelligence behind the generated IDs, where it will try to track those
that are reserved and reuse those that are not in use any more. I don't
recall details at the moment on the implementation so I'm not sure how
bulletproof it is, but it should be transparent to the application code.
--
Robin Dunn
Software Craftsman
http://wxPython.org
--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
raf
2014-10-19 22:58:53 UTC
Permalink
Post by Robin Dunn
Post by raf
Hi,
windows-8.1, python-2.7.8, wxpython-2.8.12.1
I have an application with a large dynamic popup menu.
Every time I construct it, I use ID_ANY as the id
for all the menu items.
After calling frame.PopupMenu(menu), I call menu.Delete()
but all of the ids used in the menu remain effectively
claimed and the next time the menu is constructed,
the ids used by the new menu items are higher than the
last time.
I assume that's ok because http://wiki.wxpython.org/Getting%20Started
says "You can make your own IDs, but there is no reason to do that."
However, occasionally I get reports from the users that when they
select a menu item, the application behaves as though some other
completely unrelated menu item had been selected.
I added some logging to see what was going on and asked them to
tell me when it next happened which it just has. It seems that the
problem happened the first time the user selected an item
after the menu item ids has exceeded 2**16. This might be an
unimportant coincidence. I only have one data point. But it
might be relevant.
It is. IIRC, Windows has a limit for menu IDs but a different limit
for control IDs. In 2.8 and prior[1] the IDs generated for wx.ID_ANY
(and those returned from wx.NewId()) are basically just an
incrementing global variable with almost no smarts behind it. There
is also wx.RegisterId(val) which will bump the auto-increment
sequence to val+1 so you can reserve some IDs that way if you want,
but you can still run into issues if the value wraps around and comes
back to IDs that you may still be using somewhere. And then there are
problems when the ID passes some artificial limit that the platform
imposes.
Post by raf
When the problem occurs, the id of the selected menu item is a
much lower number than the ids of any of the menu items that
exist in the menu at the time. It looks as though it's using
a much earlier id from a previous incarnation of the menu.
Does anyone have any idea what might be going wrong?
If it could have something to do with the ever increasing ids,
is there a way to tell wx to reset its next-available-id to
be one more than the currently used id?
Would using application-defined ids be ok or might other uses
of ID_ANY reuse ids that I've chosen?
What I've tended to do in situations like this where there will be
lots of items needing IDs being created, is to go ahead and use fixed
ID values for the items, but use wx.NewId() to give me the ID values.
That way they won't conflict with any other IDs that are still being
generated with wx.ID_ANY (as long as they don't wrap around, but then
that is what you are trying to prevent by doing this) and they will
also not conflict with any stock IDs. For example, I'll have globals
MY_ID_1 = wx.NewId()
MY_ID_2 = wx.NewId()
etc.
and then use those IDs where I create the popup menus. Presetting
your menu IDs like that also means that you don't need to Bind/Unbind
the event handlers each time you popup the menu, just do it once at
the beginning of the program.
[1] There was a change made in the 2.9 series that puts some more
intelligence behind the generated IDs, where it will try to track
those that are reserved and reuse those that are not in use any more.
I don't recall details at the moment on the implementation so I'm not
sure how bulletproof it is, but it should be transparent to the
application code.
--
Robin Dunn
Software Craftsman
http://wxPython.org
Thanks, Robin. That's a great suggestion. I'm sure it'll fix my problem.

Cheers,
raf
--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Loading...