Scope of keyboard shortcuts

When a letter in a widget label is prefixed with “&”, the letter is treated as a keyboard shortcut. Then, when pressing Alt+, the corresponding widget is given focus.

The problem is, that the scope where the shortcut works is very limitted. It seems to me that from the currently focused widget you can navigate only to other widgets at the same (hierarchy) level or below. For instance, take this wxPython script:
import wx

class TestFrame ( wx.Frame ):

def __init__( self, parent ):
    wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 265,563 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
   
    self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
   
    sbSizer4 = wx.StaticBoxSizer( wx.StaticBox( self, wx.ID_ANY, u"Sizer + panel + sizer" ), wx.VERTICAL )
   
    self.m_panel20 = wx.Panel( sbSizer4.GetStaticBox(), wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
    self.m_panel20.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_INFOBK ) )
   
    gbSizer3 = wx.GridBagSizer( 0, 0 )
    gbSizer3.SetFlexibleDirection( wx.BOTH )
    gbSizer3.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
   
    self.m_panel22 = wx.Panel( self.m_panel20, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
    self.m_panel22.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_ACTIVECAPTION ) )
   
    gbSizer2 = wx.GridBagSizer( 0, 0 )
    gbSizer2.SetFlexibleDirection( wx.BOTH )
    gbSizer2.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
   
    self.m_staticText31 = wx.StaticText( self.m_panel22, wx.ID_ANY, u"Panel + sizer", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.m_staticText31.Wrap( -1 )
    gbSizer2.Add( self.m_staticText31, wx.GBPosition( 0, 0 ), wx.GBSpan( 1, 2 ), wx.ALL, 5 )
   
    self.m_staticText20 = wx.StaticText( self.m_panel22, wx.ID_ANY, u"&A", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.m_staticText20.Wrap( -1 )
    gbSizer2.Add( self.m_staticText20, wx.GBPosition( 1, 0 ), wx.GBSpan( 1, 1 ), wx.ALL, 5 )
   
    self.m_textCtrl19 = wx.TextCtrl( self.m_panel22, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
    gbSizer2.Add( self.m_textCtrl19, wx.GBPosition( 1, 1 ), wx.GBSpan( 1, 1 ), wx.ALL, 5 )
   
    sbSizer8 = wx.StaticBoxSizer( wx.StaticBox( self.m_panel22, wx.ID_ANY, u"Sizer only" ), wx.HORIZONTAL )
   
    self.m_staticText21 = wx.StaticText( sbSizer8.GetStaticBox(), wx.ID_ANY, u"&B", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.m_staticText21.Wrap( -1 )
    sbSizer8.Add( self.m_staticText21, 0, wx.ALL, 5 )
   
    self.m_textCtrl20 = wx.TextCtrl( sbSizer8.GetStaticBox(), wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
    sbSizer8.Add( self.m_textCtrl20, 0, wx.ALL, 5 )
   
   
    gbSizer2.Add( sbSizer8, wx.GBPosition( 2, 0 ), wx.GBSpan( 1, 2 ), 0, 5 )
   
    self.m_staticText23 = wx.StaticText( self.m_panel22, wx.ID_ANY, u"&C", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.m_staticText23.Wrap( -1 )
    gbSizer2.Add( self.m_staticText23, wx.GBPosition( 3, 0 ), wx.GBSpan( 1, 1 ), wx.ALL, 5 )
   
    self.m_textCtrl22 = wx.TextCtrl( self.m_panel22, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
    gbSizer2.Add( self.m_textCtrl22, wx.GBPosition( 3, 1 ), wx.GBSpan( 1, 1 ), wx.ALL, 5 )
   
   
    self.m_panel22.SetSizer( gbSizer2 )
    self.m_panel22.Layout()
    gbSizer2.Fit( self.m_panel22 )
    gbSizer3.Add( self.m_panel22, wx.GBPosition( 0, 0 ), wx.GBSpan( 1, 2 ), wx.EXPAND |wx.ALL, 5 )
   
    self.m_staticText28 = wx.StaticText( self.m_panel20, wx.ID_ANY, u"&P", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.m_staticText28.Wrap( -1 )
    gbSizer3.Add( self.m_staticText28, wx.GBPosition( 1, 0 ), wx.GBSpan( 1, 1 ), wx.ALL, 5 )
   
    self.m_textCtrl26 = wx.TextCtrl( self.m_panel20, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
    gbSizer3.Add( self.m_textCtrl26, wx.GBPosition( 1, 1 ), wx.GBSpan( 1, 1 ), wx.ALL, 5 )
   
    sbSizer9 = wx.StaticBoxSizer( wx.StaticBox( self.m_panel20, wx.ID_ANY, u"Sizer only" ), wx.HORIZONTAL )
   
    self.m_staticText30 = wx.StaticText( sbSizer9.GetStaticBox(), wx.ID_ANY, u"&Q", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.m_staticText30.Wrap( -1 )
    sbSizer9.Add( self.m_staticText30, 0, wx.ALL, 5 )
   
    self.m_textCtrl27 = wx.TextCtrl( sbSizer9.GetStaticBox(), wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
    sbSizer9.Add( self.m_textCtrl27, 0, wx.ALL, 5 )
   
   
    gbSizer3.Add( sbSizer9, wx.GBPosition( 2, 0 ), wx.GBSpan( 1, 2 ), wx.EXPAND, 5 )
   
    self.m_staticText32 = wx.StaticText( self.m_panel20, wx.ID_ANY, u"&R", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.m_staticText32.Wrap( -1 )
    gbSizer3.Add( self.m_staticText32, wx.GBPosition( 3, 0 ), wx.GBSpan( 1, 1 ), wx.ALL, 5 )
   
    self.m_textCtrl29 = wx.TextCtrl( self.m_panel20, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
    gbSizer3.Add( self.m_textCtrl29, wx.GBPosition( 3, 1 ), wx.GBSpan( 1, 1 ), wx.ALL, 5 )
   
    sbSizer5 = wx.StaticBoxSizer( wx.StaticBox( self.m_panel20, wx.ID_ANY, u"Sizer + panel + sizer" ), wx.VERTICAL )
   
    self.m_panel23 = wx.Panel( sbSizer5.GetStaticBox(), wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
    self.m_panel23.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) )
   
    fgSizer5 = wx.FlexGridSizer( 0, 2, 0, 0 )
    fgSizer5.SetFlexibleDirection( wx.BOTH )
    fgSizer5.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
   
    self.m_staticText25 = wx.StaticText( self.m_panel23, wx.ID_ANY, u"&X", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.m_staticText25.Wrap( -1 )
    fgSizer5.Add( self.m_staticText25, 0, wx.ALL, 5 )
   
    self.m_textCtrl23 = wx.TextCtrl( self.m_panel23, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
    fgSizer5.Add( self.m_textCtrl23, 0, wx.ALL, 5 )
   
    self.m_staticText26 = wx.StaticText( self.m_panel23, wx.ID_ANY, u"&Y", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.m_staticText26.Wrap( -1 )
    fgSizer5.Add( self.m_staticText26, 0, wx.ALL, 5 )
   
    self.m_textCtrl24 = wx.TextCtrl( self.m_panel23, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
    fgSizer5.Add( self.m_textCtrl24, 0, wx.ALL, 5 )
   
    self.m_staticText27 = wx.StaticText( self.m_panel23, wx.ID_ANY, u"&Z", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.m_staticText27.Wrap( -1 )
    fgSizer5.Add( self.m_staticText27, 0, wx.ALL, 5 )
   
    self.m_textCtrl25 = wx.TextCtrl( self.m_panel23, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
    fgSizer5.Add( self.m_textCtrl25, 0, wx.ALL, 5 )
   
   
    self.m_panel23.SetSizer( fgSizer5 )
    self.m_panel23.Layout()
    fgSizer5.Fit( self.m_panel23 )
    sbSizer5.Add( self.m_panel23, 1, wx.EXPAND |wx.ALL, 5 )
   
   
    gbSizer3.Add( sbSizer5, wx.GBPosition( 4, 0 ), wx.GBSpan( 1, 2 ), wx.EXPAND, 5 )
   
   
    self.m_panel20.SetSizer( gbSizer3 )
    self.m_panel20.Layout()
    gbSizer3.Fit( self.m_panel20 )
    sbSizer4.Add( self.m_panel20, 1, wx.EXPAND |wx.ALL, 5 )
   
   
    self.SetSizer( sbSizer4 )
    self.Layout()
   
    self.Centre( wx.BOTH )

if name == “main”:
app = wx.App(False)
frame = TestFrame(None)
frame.Fit()
frame.Show()
app.MainLoop()

``

In this example, you can navigate from “P” and “R” anywhere (by pressing the corresponding Alt+ shortcut), but from “B” and “Q” you’ll get nowhere.
Question: How to make the keyboard shortcuts working globally within a chosen panel?