tab order problem

hi,

python 2.5.2
wxpython 2.8.8.1
macosx 10.4.11

i have an app with a splitter window.
the left hand side contains a treectrl.
the right hand side contains an auinotebook.
there is a widget-filled scrolledpanel in the auinotebook
containing textctrls, comboboxes and datepickerctrls.

i would like tabbing to stay within the panel but it doesn't.
pressing tab traverses all of the widgets and then,
instead of returning to the first widget, the focus
goes over to the treectrl in the left hand side of
the splitter window (and never comes back). i'd prefer
to enlist Ctrl-Tab of something to make that happen.

i tried to use the following code from
http://wiki.wxpython.org/Getting%20Started:

    order = (control1, control2, control3, ...)
    for i in xrange(len(order) - 1):
        order[i+1].MoveAfterInTabOrder(order[i])
     
but it had no effect. i thought it might be because
of what looks to be a bug in that code. i.e. that
one of the widgets is left out. there is no equivalent
to:

    order[0].MoveAfterInTabOrder(order[-1])

so i tried a slightly different version:

    for i in range(len(order)):
        order[i].MoveAfterInTabOrder(order[i - 1])

but that didn't fix it. i guess it probably wasn't a bug
after all. maybe it's based on relative id numbers rather
than pointers (in which case, how do i make it cycle?)

anyway, the tab order behaviour is strange. once the focus
is stuck in the treectrl on the left hand side, there is one
textctrl widget in the panel of the auinotebook (inside a
staticboxsizer) that won't accept focus even by clicking on it!
i have to first click on the auinotebook panel's tab and then
press the tab key to get it to accept focus. and the datepickerctrl
widgets then seem to get skipped in the tab order. perhaps not
skipped but rather when it's meant to have focus, it doesn't look
like it has focus and it doesn't receive keystrokes but on the other
hand, no other widget has focus either.

does anyone have any idea what i'm doing wrong?

i've attached a cut down version of the application to
demonstrate but it sometimes behaves differently. if you
start the app and press enter, it'll create the auinotebook
pane and set focus to the first widget. pressing tab now
progresses until it reaches the datepickerctrl labelled
"Left:" after that, pressing tab briefly goes to the next
widget and then continually returns to the Left:
datepickerctrl. sometimes it exhibits the behaviour
described earlier.

i tried disabling the EVT_SET_FOCUS handlers and the
CallAfter SetSelection/SetMark but that didn't fix anything
so they're still in the attached code.

this is maddening behaviour. what i have i done to cause it?
i really need this application to be usable without the need
to use the mouse and so need complete control over the
focus.

cheers,
raf

p.s. any ideas about the datepickerctrl problem i posted
earlier? that it uses american date formants instead of the
date format specified by the system (like it is supposed to?)

grr.py (23.2 KB)

raf wrote:

does anyone have any idea what i'm doing wrong?

i've attached a cut down version of the application to
demonstrate but it sometimes behaves differently. if you
start the app and press enter, it'll create the auinotebook
pane and set focus to the first widget. pressing tab now
progresses until it reaches the datepickerctrl labelled
"Left:" after that, pressing tab briefly goes to the next
widget and then continually returns to the Left:
datepickerctrl. sometimes it exhibits the behaviour
described earlier.

i tried disabling the EVT_SET_FOCUS handlers and the
CallAfter SetSelection/SetMark but that didn't fix anything
so they're still in the attached code.

this is maddening behaviour. what i have i done to cause it?
i really need this application to be usable without the need
to use the mouse and so need complete control over the
focus.

There are two problems, one is yours and one is AUI's. First a little behind-the-scenes info. The way that tab traversal typically works (there are some platform specific issues, but most of this is in the common code) in a normal situation is something like this:

* Tabbing moves focus to the next sibling on the same parent that accepts the focus, and when it gets to the end of the children of the parent control is transfered up the containment hierarchy to some other (grand)parent that is willing to handle tab traversal, if there isn't one then focus is moved back to the first child in the tab traversal order of the same parent.

* Tab order is by default the order of creation of the widgets. The Move*InTabOrder methods simply manipulate the order of the children in this list.

* Not all widgets will accept the focus, if not then they are just skipped when looking for the next item in the order. Widget classes can control this by overriding the AcceptsFocus method (unfortunately in wxPython it is only overridable in the wx.Py classes like wx.PyControl.)

* When a tab traversal supporting container window receives focus it will normally try to set focus to the child widget that last had the focus. (Like when the frame is activated after another app was active, or when a modal dialog is closed.) There are some things that can sometimes interfere with this however...

Not to your specific example... The first problem is that you are specifying style=wx.BORDER_SUNKEN for your panels. There's no problem with the border itself, it's the fact that you are no longer using the default style of wx.TAB_TRAVERSAL. Change them to be style=BORDER_SUNKEN|wx.TAB_TRAVERSAL instead. Once you do that then when the focus is in the tree and tab is pressed, the traversal code will look up to the splitter window which will then go to the right-side panel which will then give the focus to the AuiNotebook.

This is where the second problem is. The AuiNotebook is not properly behaving like a container as far as the tab traversal is concerned. (Please create a bug report about this.) You can partially work around this by also using the wx.TAB_TRAVERSAL style with the AuiNotebook, but it still has a problem as it takes a few extra presses of the tab key to get through the AuiNotebook and the AuiTabCtrl (with no visual clue what is happening) until focus reaches the page window and it is then reset to the first widget again. You can probably work around this part by hooking set_focus handlers to the AuiNotbook and its AuiTabCtrl child and resetting the focus to the current page window, or maybe just use navigation events so back-tabs will be handled too. You'll need to experiment a bit...

p.s. any ideas about the datepickerctrl problem i posted
earlier? that it uses american date formants instead of the
date format specified by the system (like it is supposed to?)

I haven't checked into it yet.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin Dunn wrote:

raf wrote:

>does anyone have any idea what i'm doing wrong?
>
>i've attached a cut down version of the application to
>demonstrate but it sometimes behaves differently. if you
>start the app and press enter, it'll create the auinotebook
>pane and set focus to the first widget. pressing tab now
>progresses until it reaches the datepickerctrl labelled
>"Left:" after that, pressing tab briefly goes to the next
>widget and then continually returns to the Left:
>datepickerctrl. sometimes it exhibits the behaviour
>described earlier.
>
>i tried disabling the EVT_SET_FOCUS handlers and the
>CallAfter SetSelection/SetMark but that didn't fix anything
>so they're still in the attached code.
>
>this is maddening behaviour. what i have i done to cause it?
>i really need this application to be usable without the need
>to use the mouse and so need complete control over the
>focus.

There are two problems, one is yours and one is AUI's. First a little
behind-the-scenes info. The way that tab traversal typically works
(there are some platform specific issues, but most of this is in the
common code) in a normal situation is something like this:

* Tabbing moves focus to the next sibling on the same parent that
accepts the focus, and when it gets to the end of the children of the
parent control is transfered up the containment hierarchy to some other
(grand)parent that is willing to handle tab traversal, if there isn't
one then focus is moved back to the first child in the tab traversal
order of the same parent.

* Tab order is by default the order of creation of the widgets. The
Move*InTabOrder methods simply manipulate the order of the children in
this list.

* Not all widgets will accept the focus, if not then they are just
skipped when looking for the next item in the order. Widget classes can
control this by overriding the AcceptsFocus method (unfortunately in
wxPython it is only overridable in the wx.Py classes like wx.PyControl.)

the widget that wouldn't accept focus was a TextCtrl so it
should. i fixed that by taking it out of the StaticBoxSizer
that it was in. that was the only difference between it and
the other widgets. it doesn't look at good now but that's
less important.

* When a tab traversal supporting container window receives focus it
will normally try to set focus to the child widget that last had the
focus. (Like when the frame is activated after another app was active,
or when a modal dialog is closed.) There are some things that can
sometimes interfere with this however...

Not to your specific example... The first problem is that you are
specifying style=wx.BORDER_SUNKEN for your panels. There's no problem
with the border itself, it's the fact that you are no longer using the
default style of wx.TAB_TRAVERSAL. Change them to be
style=BORDER_SUNKEN|wx.TAB_TRAVERSAL instead. Once you do that then
when the focus is in the tree and tab is pressed, the traversal code
will look up to the splitter window which will then go to the right-side
panel which will then give the focus to the AuiNotebook.

strangely enough, that isn't what happened. the focus still
didn't return to the right hand side. i tried removing the
panel between the splitter window and the auinotebook as
well but that didn't change anything either.

This is where the second problem is. The AuiNotebook is not properly
behaving like a container as far as the tab traversal is concerned.
(Please create a bug report about this.)

done (ticket #9911)

You can partially work around
this by also using the wx.TAB_TRAVERSAL style with the AuiNotebook, but
it still has a problem as it takes a few extra presses of the tab key to
get through the AuiNotebook and the AuiTabCtrl (with no visual clue what
is happening) until focus reaches the page window and it is then reset
to the first widget again. You can probably work around this part by
hooking set_focus handlers to the AuiNotbook and its AuiTabCtrl child
and resetting the focus to the current page window, or maybe just use
navigation events so back-tabs will be handled too. You'll need to
experiment a bit...
--
Robin Dunn

since i really wanted tabbing to cycle within a single
auinotebook pane anyway (and use something like Ctrl-Tab
to move between panes), i decided to take over the tabbing
myself.

based on your responses to others in the archives, i
attempted this by preventing TAB_TRAVERSAL everywhere and
using WANTS_CHARS and TE_PROCESS_TAB in all the relevant
widgets. there was a problem with that on macosx (i.e.
ComboBox doesn't receive EVT_CHAR events for tab characters)
but that was easily resolved (because it does receive
EVT_KEY_DOWN events for tab characters). it now works fine
on macosx and linux (where comboBoxreceives both
EVT_KEY_DOWN and EVT_CHAR events for tab characters) but
doesn't work at all on windows where ComboBox doesn't
receive either event for tab characters (this is without
TAB_TRAVERSAL and with WANTS_CHARS|TE_PROCESS_TAB of course).

so on windows(nt), tabbing stops at the first ComboBox
and goes no further. windows(xp) is the system that it
really needs to work on.

can you suggest what i might do to resolve that? i'm hoping
it's something simple.

below are the detailed notes from the attached demo program.
it shows that my remaining tab-related problem is that on windows,
without TAB_TRAVERSAL and with WANTS_CHARS|TE_PROCESS_TAB,
ComboBox doesn't receive EVT_CHAR or EVT_KEY_DOWN events
when the tab key is pressed. what can i do now?

manny thanks,
raf

# Having disabled TAB_TRAVERSAL everywhere and used style=WANTS_CHARS
# for all widgets (and TE_PROCESS_TAB as well for TextCtrl and ComboBox
# widgets), here are the differences I see between different platforms
# with regards to tabbing and shift-tabbing between widgets.

grr.py (29.7 KB)

···

#
# On MacOSX, ComboBox doesn't receive EVT_CHAR events for tab characters.
# However, tabbing does work through ComboBox widgets (somehow).
# However, shift-tabbing when a ComboBox has focus is
# the same as tab i.e. Focus moves to the next widget,
# not the previous one. So, tabbing forward cycles fine,
# but shift-tabbing backwards gets stuck on the first
# ComboBox encountered. The other widgets (TextCtrl,
# CheckBox and Button) were fine with shift-tabbing.
# ComboBox does receive EVT_KEY_DOWN events for tab characters
# and by handling tab and shift-tab here on MacOSX,
# shift-tabbing backwards across ComboBox widgets works.
#
# On Linux, using only EVT_CHAR events, tabbing forwards and
# shift-tabbing backwards works fine with all widgets that
# I used (TextCtrl, ComboBox, CheckBox and Button).
#
# On WinNT, ComboBox receives two EVT_SET_FOCUS events and doesn't
# receive EVT_CHAR or EVT_KEY_DOWN events for tab characters.
# So, tabbing forwards stops at the first ComboBox.
# Shift-tabbing in a ComboBox sends focus to the
# only Button widget (last in tab order but that might not be relevant).
# Tabbing from the button makes focus disappear but shift-tabbing
# makes it return to the Button. Shift-tabbing when the button has
# focus does nothing.
#
# MAC: tab combo: EES.keydown(handletab), TE.childfocus
# MAC: tab other: EES.keydown(handletab), TE.childfocus
# LIN: tab combo: EES.keydown, CE.keydown, EES.char(handletab), TE.setfocus
# LIN: tab other: EES.keydown, EES.char(handletab), TE.setfocus
# WIN: tab combo: nothing at all...
# WIN: tab other: EES.keydown, EES.char(handletab), TE.setfocus, TE.setfocus
#
# Where:
# EES = class EditEmployeeScreen
# TE = class TextEntry(TextCtrl)
# CE = class CodeEntry(ComboBox)
# --------------------------------------------------------------------
# Other platform inconsistencies:
#
# On MacOSX, ComboBox doesn't receive EVT_SET_FOCUS but it
# does receive EVT_CHILD_FOCUS. This isn't related to
# tabbing but rather to automatically selecting all text in a
# widget when it receives focus (as the following code does).
#
# On Linux/GTK, in a ComboBox, when some text is selected and
# the user types a character, there is one EVT_TEXT event where
# the selected text is deleted, then there is a second EVT_TEXT
# event with the new character. This is playing havoc with my
# auto-completing ComboBox. More on that later.
#

raf wrote:

Robin Dunn wrote:

* Not all widgets will accept the focus, if not then they are just skipped when looking for the next item in the order. Widget classes can control this by overriding the AcceptsFocus method (unfortunately in wxPython it is only overridable in the wx.Py classes like wx.PyControl.)

the widget that wouldn't accept focus was a TextCtrl so it
should. i fixed that by taking it out of the StaticBoxSizer
that it was in. that was the only difference between it and
the other widgets. it doesn't look at good now but that's
less important.

The focus was probably actually stuck in some widget before the TextCtrl in the tab order.

Not to your specific example... The first problem is that you are specifying style=wx.BORDER_SUNKEN for your panels. There's no problem with the border itself, it's the fact that you are no longer using the default style of wx.TAB_TRAVERSAL. Change them to be style=BORDER_SUNKEN|wx.TAB_TRAVERSAL instead. Once you do that then when the focus is in the tree and tab is pressed, the traversal code will look up to the splitter window which will then go to the right-side panel which will then give the focus to the AuiNotebook.

strangely enough, that isn't what happened. the focus still
didn't return to the right hand side. i tried removing the
panel between the splitter window and the auinotebook as
well but that didn't change anything either.

It did fix it on Windows in my tests, but the fact that there's a platform difference here doesn't surprise me too much. Also, on Mac the ability to tab to some types of widgets is turned off by default, and needs to be turned on using the Full Keyboard Access option in System Preferences.

since i really wanted tabbing to cycle within a single
auinotebook pane anyway (and use something like Ctrl-Tab
to move between panes), i decided to take over the tabbing
myself.

based on your responses to others in the archives, i
attempted this by preventing TAB_TRAVERSAL everywhere and
using WANTS_CHARS and TE_PROCESS_TAB in all the relevant
widgets. there was a problem with that on macosx (i.e.
ComboBox doesn't receive EVT_CHAR events for tab characters)
but that was easily resolved (because it does receive
EVT_KEY_DOWN events for tab characters). it now works fine
on macosx and linux (where comboBoxreceives both
EVT_KEY_DOWN and EVT_CHAR events for tab characters) but
doesn't work at all on windows where ComboBox doesn't
receive either event for tab characters (this is without
TAB_TRAVERSAL and with WANTS_CHARS|TE_PROCESS_TAB of course).

so on windows(nt), tabbing stops at the first ComboBox
and goes no further. windows(xp) is the system that it
really needs to work on.

can you suggest what i might do to resolve that? i'm hoping
it's something simple.

Adding something like this will help you debug it and maybe help with finding a workaround:

  global cl
  def showfocus():
    print wx.Window.FindFocus()
    cl.Restart()
  cl = wx.CallLater(3000, showfocus)

I'm not sure why but it looks like focus is going to the AuiNotebook when tab is pressed in a combobox.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin Dunn wrote:

raf wrote:
>Robin Dunn wrote:

>>* Not all widgets will accept the focus, if not then they are just
>>skipped when looking for the next item in the order. Widget classes can
>>control this by overriding the AcceptsFocus method (unfortunately in
>>wxPython it is only overridable in the wx.Py classes like wx.PyControl.)
>
>the widget that wouldn't accept focus was a TextCtrl so it
>should. i fixed that by taking it out of the StaticBoxSizer
>that it was in. that was the only difference between it and
>the other widgets. it doesn't look at good now but that's
>less important.

The focus was probably actually stuck in some widget before the TextCtrl
in the tab order.

>>Not to your specific example... The first problem is that you are
>>specifying style=wx.BORDER_SUNKEN for your panels. There's no problem
>>with the border itself, it's the fact that you are no longer using the
>>default style of wx.TAB_TRAVERSAL. Change them to be
>>style=BORDER_SUNKEN|wx.TAB_TRAVERSAL instead. Once you do that then
>>when the focus is in the tree and tab is pressed, the traversal code
>>will look up to the splitter window which will then go to the right-side
>>panel which will then give the focus to the AuiNotebook.
>
>strangely enough, that isn't what happened. the focus still
>didn't return to the right hand side. i tried removing the
>panel between the splitter window and the auinotebook as
>well but that didn't change anything either.

It did fix it on Windows in my tests, but the fact that there's a

perhaps the windows i'm using (nt4) is too old to be indicative.

platform difference here doesn't surprise me too much. Also, on Mac the
ability to tab to some types of widgets is turned off by default, and
needs to be turned on using the Full Keyboard Access option in System
Preferences.

i did have 'Full Keyboard Access' turned on.

>since i really wanted tabbing to cycle within a single
>auinotebook pane anyway (and use something like Ctrl-Tab
>to move between panes), i decided to take over the tabbing
>myself.
>
>based on your responses to others in the archives, i
>attempted this by preventing TAB_TRAVERSAL everywhere and
>using WANTS_CHARS and TE_PROCESS_TAB in all the relevant
>widgets. there was a problem with that on macosx (i.e.
>ComboBox doesn't receive EVT_CHAR events for tab characters)
>but that was easily resolved (because it does receive
>EVT_KEY_DOWN events for tab characters). it now works fine
>on macosx and linux (where comboBoxreceives both
>EVT_KEY_DOWN and EVT_CHAR events for tab characters) but
>doesn't work at all on windows where ComboBox doesn't
>receive either event for tab characters (this is without
>TAB_TRAVERSAL and with WANTS_CHARS|TE_PROCESS_TAB of course).
>
>so on windows(nt), tabbing stops at the first ComboBox
>and goes no further. windows(xp) is the system that it
>really needs to work on.
>
>can you suggest what i might do to resolve that? i'm hoping
>it's something simple.

Adding something like this will help you debug it and maybe help with
finding a workaround:

  global cl
  def showfocus():
    print wx.Window.FindFocus()
    cl.Restart()
  cl = wx.CallLater(3000, showfocus)

I'm not sure why but it looks like focus is going to the AuiNotebook
when tab is pressed in a combobox.

--
Robin Dunn
Software Craftsman

thanks. that was very helpful.

So that means that turning off TAB_TRAVERSAL doesn't work on Windows.
Or at least when there's an AuiNotebook and ComboBoxes or Buttons involved.

I set up an EVT_SET_FOCUS for the AuiNotebook but since the actual Tab
keystroke event is lost, it can't tell if it was Tab or Shift-Tab.
So, using this approach, it's possible to make Tab cycle through the controls
within an AuiNotebook page but you can't reliably get Shift-Tab to work as well.

What I had to do, to make it work on Windows, was to make Tab and Shift-Tab
accelerators. That seemed a little extreme but it worked completely.

I had already made Ctrl-Tab and Shift-Ctrl-Tab cycle through AuiNotebook
pages by making them accelerators. In doing so, I discovered that, on
Linux, Tab can't be used as an accelerator. If you try, it can show up
in menus as though it was working but the accelerator handler isn't called.
Instead, EVT_KEY_DOWN events are generated.

I also noticed that without TAB_TRAVERSAL and with WANTS_CHARS, on MacOSX,
ComboBoxes don't receive EVT_CHAR events when Tab is pressed but they do
receive EVT_KEY_DOWN events.

I came across other inconsistencies so, below is a list of
what-look-to-me-to-be-platform-specific-bugs.

Would you agree? Should I enter bug reports for each of these?

The attached program demonstrates them. By changing the flags
at the top of the program, either the incomplete hack or the
complete hack can be demonstrated as well.

many thanks,
raf

List of platform-specific bugs

wx-platform-inconsistencies.py (40.5 KB)

···

------------------------------
MacOSX Platform: macosx-10.4.11, python-2.5.2, wxpython-2.8.8.1 (mac-unicode)
Linux Platform: linux-2.6.24, python-2.5.2, wxpython-2.8.7.1 (gtk2-unicode)
Windows Platform: nt4sp6, python-2.5.2, wxpython-2.8.8.1 (msw-unicode)

1. On Windows, disabling TAB_TRAVERSAL and using WANTS_CHARS doesn't
work with ComboBoxes or Buttons that are inside an AuiNotebook. I
don't know if the presence of the AuiNotebook is relevant but when
the Tab key is pressed while focus is in a ComboBox or Button, there
is no EVT_CHAR event as there should be. Instead the focus moves to
the AuiNotebook itself and is lost to the user (until they click).

2. On Windows, ComboBox controls receive two EVT_SET_FOCUS events
when they receive focus instead of just one.

3. On MacOSX, ComboBox and TextCtrl don't receive EVT_SET_FOCUS events
like on other platforms. Instead they receive EVT_CHILD_FOCUS events.

4. On MacOSX, without TAB_TRAVERSAL and with WANTS_CHARS, ComboBox
doesn't get EVT_CHAR events for Tab keys as it should but it does
get EVT_KEY_DOWN events.

5. On Linux, the Tab key can't be used in an accelerator, with or
without modifiers. They can appear in menus as accelerators but
when the Tab key is pressed, EVT_KEY_DOWN events are generated.
The appropriate menu handler is not called.

6. On linux, if a ComboBox has selected text, and the user types a character,
there are two EVT_TEXT events generated. The first has the text with the
selected text absent. The second has the text with the new character present.
On MacOSX and Windows, this all happens with a single EVT_TEXT event being
generated. This makes auto-completing controls more difficult.

raf wrote:

I came across other inconsistencies so, below is a list of
what-look-to-me-to-be-platform-specific-bugs.

Would you agree? Should I enter bug reports for each of these?

Yes, but see below.

The attached program demonstrates them. By changing the flags
at the top of the program, either the incomplete hack or the
complete hack can be demonstrated as well.

many thanks,
raf

List of platform-specific bugs
------------------------------
MacOSX Platform: macosx-10.4.11, python-2.5.2, wxpython-2.8.8.1 (mac-unicode)
Linux Platform: linux-2.6.24, python-2.5.2, wxpython-2.8.7.1 (gtk2-unicode)
Windows Platform: nt4sp6, python-2.5.2, wxpython-2.8.8.1 (msw-unicode)

1. On Windows, disabling TAB_TRAVERSAL and using WANTS_CHARS doesn't
work with ComboBoxes or Buttons that are inside an AuiNotebook. I
don't know if the presence of the AuiNotebook is relevant but when
the Tab key is pressed while focus is in a ComboBox or Button, there
is no EVT_CHAR event as there should be. Instead the focus moves to
the AuiNotebook itself and is lost to the user (until they click).

2. On Windows, ComboBox controls receive two EVT_SET_FOCUS events
when they receive focus instead of just one.

3. On MacOSX, ComboBox and TextCtrl don't receive EVT_SET_FOCUS events
like on other platforms. Instead they receive EVT_CHILD_FOCUS events.

Focus events are working fine for me with a wx.TextCtrl. Are you sure about your results? For wx.ComboBox it is because it is a composite control, but that can be fixed to properly send the focus events as if they were coming from the composite.

···

4. On MacOSX, without TAB_TRAVERSAL and with WANTS_CHARS, ComboBox
doesn't get EVT_CHAR events for Tab keys as it should but it does
get EVT_KEY_DOWN events.

5. On Linux, the Tab key can't be used in an accelerator, with or
without modifiers. They can appear in menus as accelerators but
when the Tab key is pressed, EVT_KEY_DOWN events are generated.
The appropriate menu handler is not called.

6. On linux, if a ComboBox has selected text, and the user types a character,
there are two EVT_TEXT events generated. The first has the text with the
selected text absent. The second has the text with the new character present.
On MacOSX and Windows, this all happens with a single EVT_TEXT event being
generated. This makes auto-completing controls more difficult.

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin Dunn wrote:

raf wrote:

>I came across other inconsistencies so, below is a list of
>what-look-to-me-to-be-platform-specific-bugs.
>
>Would you agree? Should I enter bug reports for each of these?

Yes, but see below.

ok.

>The attached program demonstrates them. By changing the flags
>at the top of the program, either the incomplete hack or the
>complete hack can be demonstrated as well.
>
>many thanks,
>raf
>
>List of platform-specific bugs
>------------------------------
>MacOSX Platform: macosx-10.4.11, python-2.5.2, wxpython-2.8.8.1
>(mac-unicode)
>Linux Platform: linux-2.6.24, python-2.5.2, wxpython-2.8.7.1 (gtk2-unicode)
>Windows Platform: nt4sp6, python-2.5.2, wxpython-2.8.8.1 (msw-unicode)
>
>1. On Windows, disabling TAB_TRAVERSAL and using WANTS_CHARS doesn't
>work with ComboBoxes or Buttons that are inside an AuiNotebook. I
>don't know if the presence of the AuiNotebook is relevant but when
>the Tab key is pressed while focus is in a ComboBox or Button, there
>is no EVT_CHAR event as there should be. Instead the focus moves to
>the AuiNotebook itself and is lost to the user (until they click).
>
>2. On Windows, ComboBox controls receive two EVT_SET_FOCUS events
>when they receive focus instead of just one.
>
>3. On MacOSX, ComboBox and TextCtrl don't receive EVT_SET_FOCUS events
>like on other platforms. Instead they receive EVT_CHILD_FOCUS events.

Focus events are working fine for me with a wx.TextCtrl. Are you sure
about your results?

yes, i'm sure. under linux using the previously attached
program (wx-platform-inconsistencies.py) clicking in
TextCtrl and ComboBox controls results in the program
printing lines like:

  TextEntry.OnSetFocus(ctrlname)
  CodeEntry.OnSetFocus(ctrlname)

on macosx, the same behaviour prints lines like:

  TextEntry.OnChildFocus(ctrlname)
  CodeEntry.OnChildFocus(text)

on windows, the same behaviour prints lines like:

  TextEntry.OnSetFocus(ctrlname)
  CodeEntry.OnSetFocus(ctrlname)

i.e. the same as linux.

odd. i wonder if anyone can reproduce the behaviour i'm seeing?

For wx.ComboBox it is because it is a composite control,
but that can be fixed to properly send the focus events as if
they were coming from the composite.

that's great. it would be good to have the same event api
across all platforms as well as the same class api.

of course, this means we have to be careful about writing
focus catching code so that it handles the current behaviour
as well as future fixed behaviour :slight_smile: but that just means
using the same handler for both events rather than calling
OnSetFocus from OnChildFocus as i did in the sample program.

thanks again for your time and expertise.

cheers,
raf

···

>4. On MacOSX, without TAB_TRAVERSAL and with WANTS_CHARS, ComboBox
>doesn't get EVT_CHAR events for Tab keys as it should but it does
>get EVT_KEY_DOWN events.
>
>5. On Linux, the Tab key can't be used in an accelerator, with or
>without modifiers. They can appear in menus as accelerators but
>when the Tab key is pressed, EVT_KEY_DOWN events are generated.
>The appropriate menu handler is not called.
>
>6. On linux, if a ComboBox has selected text, and the user types a
>character,
>there are two EVT_TEXT events generated. The first has the text with the
>selected text absent. The second has the text with the new character
>present.
>On MacOSX and Windows, this all happens with a single EVT_TEXT event being
>generated. This makes auto-completing controls more difficult.

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

raf wrote:

Robin Dunn wrote:

raf wrote:

3. On MacOSX, ComboBox and TextCtrl don't receive EVT_SET_FOCUS events
like on other platforms. Instead they receive EVT_CHILD_FOCUS events.

Focus events are working fine for me with a wx.TextCtrl. Are you sure about your results?

yes, i'm sure. under linux using the previously attached
program (wx-platform-inconsistencies.py) clicking in
TextCtrl and ComboBox controls results in the program
printing lines like:

  TextEntry.OnSetFocus(ctrlname)
  CodeEntry.OnSetFocus(ctrlname)

on macosx, the same behaviour prints lines like:

  TextEntry.OnChildFocus(ctrlname)
  CodeEntry.OnChildFocus(text)

on windows, the same behaviour prints lines like:

  TextEntry.OnSetFocus(ctrlname)
  CodeEntry.OnSetFocus(ctrlname)

i.e. the same as linux.

odd. i wonder if anyone can reproduce the behaviour i'm seeing?

Sure, everybody can. All they have to do is make the same mistake that you made. :wink: You have this in TextEntry.__init__:

    if Platform == '__WXMAC__':
      self.Bind(EVT_CHILD_FOCUS, self.OnChildFocus)
    else:
      self.Bind(EVT_SET_FOCUS, self.OnSetFocus)

If you instead bind the EVT_SET_FOCUS on Mac too then it will work like you expect. (My guess is that the textctrl is seeing it's own child focus event.)

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin Dunn wrote:

> raf wrote:
> odd. i wonder if anyone can reproduce the behaviour i'm seeing?

Sure, everybody can. All they have to do is make the same mistake that
you made. :wink: You have this in TextEntry.__init__:

    if Platform == '__WXMAC__':
      self.Bind(EVT_CHILD_FOCUS, self.OnChildFocus)
    else:
      self.Bind(EVT_SET_FOCUS, self.OnSetFocus)

If you instead bind the EVT_SET_FOCUS on Mac too then it will work like
you expect. (My guess is that the textctrl is seeing it's own child
focus event.)

of course :slight_smile: i think i wrote it that way because of
something i read in the mailing list archives but
either it was only referring to ComboBox or it should
have only been referring to ComboBox.

when i put in the bug report, i will not besmirch
the good name of TextCtrl :slight_smile:

many thanks, again,
raf