I have a panel that should receive keyboard events. It works fine on OSX and GTK (Linux).
On Windows, it receives “normal” keyboard events (letter keys, number keys, etc.) If I type an arrow key or tab key, it loses focus and gives focus to a ListCtrl in another panel. If I enter an ENTER key, it does not receive the ENTER keypress (but does not change the focus). This is not the desired behavior – I need to process the arrow keys and enter keys on the panel that initially had the focus.
There may be an event I could trap here to see where these arrow/enter/tab keypresses are going to, but I can’t spot it.
How can I either prevent this grabbing of my keystrokes or intercept it?
Attached is a simple reproduction of the problem. On OSX, when this is run, you can enter “normal” keys or arrow/tab/enter and get console confirmation that the panel’s event got them. On Windows, you can enter “normal” keys and get the same confirmation. Enter keys vanish. Tab/Arrow keys vanish and then the focus magically moves to the listctrl (you can confirm this by arrowing up/down in the list).
Digging further into archives, I found a message here that suggests adding “style=0” to my panel initialization should solve the problem, and it does. (I’m not sure what I’m overriding there–any tips would be helpful).
HOWEVER, this doesn’t actually solve my real problem – in the real program, the panel is in a MultiSplitterWindow and, when my simple test case code is updated to reflect this, we’re back to the same problem: “normal” keys and “movement keys” both are caught in OSX, but only “normal” keys in Windows and the focus is moved to the listctrl by arrow/tab keys.
Attaching update reproducible problem code, now with “style=0” on panel but in a MultiSplitterWindow.
On Wednesday, June 6, 2012 5:02:26 PM UTC-7, Joel Burton wrote:
I have a panel that should receive keyboard events. It works fine on OSX and GTK (Linux).
On Windows, it receives “normal” keyboard events (letter keys, number keys, etc.) If I type an arrow key or tab key, it loses focus and gives focus to a ListCtrl in another panel. If I enter an ENTER key, it does not receive the ENTER keypress (but does not change the focus). This is not the desired behavior – I need to process the arrow keys and enter keys on the panel that initially had the focus.
There may be an event I could trap here to see where these arrow/enter/tab keypresses are going to, but I can’t spot it.
How can I either prevent this grabbing of my keystrokes or intercept it?
Attached is a simple reproduction of the problem. On OSX, when this is run, you can enter “normal” keys or arrow/tab/enter and get console confirmation that the panel’s event got them. On Windows, you can enter “normal” keys and get the same confirmation. Enter keys vanish. Tab/Arrow keys vanish and then the focus magically moves to the listctrl (you can confirm this by arrowing up/down in the list).
Digging further into archives, I found a message here that suggests
adding "style=0" to my panel initialization should solve the problem,
and it does. (I'm not sure what I'm overriding there--any tips would be
helpful).
The default style for panels is wx.TAB_TRAVERSAL, so passing style=0 turns that off.
HOWEVER, this doesn't actually solve my real problem -- in the real
program, the panel is in a MultiSplitterWindow and, when my simple test
case code is updated to reflect this, we're back to the same problem:
"normal" keys and "movement keys" both are caught in OSX, but only
"normal" keys in Windows and the focus is moved to the listctrl by
arrow/tab keys.
On Windows wxWidgets needs to process things like arrow keys a little differently but there is an additional style that can be used to get normal char events for them. (I think it also affects the production of key-down events too.) Try using style=wx.WANTS_CHARS.
You may also want to switch to a wx.Window instead of a wx.Panel. Once you turn off tab traversal and do not have any child widgets, then there really isn't a whole lot of difference between them. However there may still be some navigation related features that could show up and effect the behaviors you want.
Finally, MultiSplitterWindow is also a wx.Panel, so it will participate in navigation and such and may also get in the way of what you are wanting. I see that it is always adding the wx.TAB_TRAVERSAL style before calling the base class __init__ so you may need to turn it off again after construction.
Robin – I appreciate your help. One small question remains; read down.
HOWEVER, this doesn’t actually solve my real problem – in the real
program, the panel is in a MultiSplitterWindow and, when my simple test
case code is updated to reflect this, we’re back to the same problem:
“normal” keys and “movement keys” both are caught in OSX, but only
“normal” keys in Windows and the focus is moved to the listctrl by
arrow/tab keys.
On Windows wxWidgets needs to process things like arrow keys a little
differently but there is an additional style that can be used to get
normal char events for them. (I think it also affects the production of
key-down events too.) Try using style=wx.WANTS_CHARS.
Adding wx.WANTS_CHARS to the style of my inner panel (the one that does, in fact, want the chars) solves the problem. Thanks!
You may also want to switch to a wx.Window instead of a wx.Panel. Once
you turn off tab traversal and do not have any child widgets, then there
really isn’t a whole lot of difference between them. However there may
still be some navigation related features that could show up and effect
the behaviors you want.
Also changed this; thanks. Early on, I found several good explanations of wx.Frame v wx.Panel, but wasn’t clear on Panel versus Window.
Finally, MultiSplitterWindow is also a wx.Panel, so it will participate
in navigation and such and may also get in the way of what you are
wanting. I see that it is always adding the wx.TAB_TRAVERSAL style
before calling the base class init so you may need to turn it off
again after construction.
Given that wx.WANTS_CHARS solves this problem. I apparently don’t need to turn off the TAB_TRAVERSAL on the splitter.
But I’m curious how I could do so best I can make it work by wholesale copying the original splitter.py MultiSplitterWindow init into a subclassed NonTraversingSplitterWindow and commenting out the line that always adds TAB_TRAVERSAL. That worked but it’s pretty ugly copying and pasting the entire init method into the subclass. You make it sound like I can adjust the style after construction, but I don’t see how. Any pointers?
Thanks!
j.
···
On Thursday, June 7, 2012 8:52:51 AM UTC-7, Robin Dunn wrote:
See wx.Window.SetWindowStyleFlag. Not all styles can be changed after construction, but I believe that wx.WANTS_CHARS can.
···
On 6/7/12 11:16 AM, Joel Burton wrote:
Finally, MultiSplitterWindow is also a wx.Panel, so it will participate
in navigation and such and may also get in the way of what you are
wanting. I see that it is always adding the wx.TAB_TRAVERSAL style
before calling the base class __init__ so you may need to turn it off
again after construction.
Given that wx.WANTS_CHARS solves this problem. I apparently don't need
to turn off the TAB_TRAVERSAL on the splitter.
But I'm curious how I could do so best I can make it work by wholesale
copying the original splitter.py MultiSplitterWindow __init__ into a
subclassed NonTraversingSplitterWindow and commenting out the line that
always adds TAB_TRAVERSAL. That worked but it's pretty ugly copying and
pasting the entire __init__ method into the subclass. You make it sound
like I can adjust the style after construction, but I don't see how. Any
pointers?