== Introduction == Accelerator keys are often a more efficient way of interacting with a GUI that are mouse gestures. However, wxPython does not appear to offer a direct way of associating the label of a textbox, or of another control, with the control itself. This recipe shows how to associate the accelerator keys implied by a collection of static labels with the appropriate controls in such a way that, when an accelerator key is pressed the associated control gains focus. == What Objects are Involved == * `wxStaticText`, for the control labels * `wxTextCtrl`, `wxComboBox` and `wxCheckBox`, as examples of controls that may be labelled with `wxStaticText` * `wxAcceleratorTable`, which is wxPython's container for information about accelerators and their associated controls. == Process Overview == In the following example: * the series of controls, including a combo box, some edit boxes and so on, are created first * a class, called `AccumAcceleratorTable`, is instantiated that will * identify accelerator keys from label texts * accumulate information about the associations among accelerators, static labels and controls for later use * create appropriate event mappings * the series of static labels corresponding to the controls are created, and information about the associations accumulated using the aforementioned class instance * the accumulated information is made available for the duration of the script's execution. Note that the method called focusHandler uses information that is accumulated in a dictionary to decide which control is to receive focus based on incoming menu event information. == Special Concerns == My main concern is that I might have failed to notice machinery that is already available in wxPython for doing this. == Code Sample == {{{ #!python from wxPython.wx import * from re import compile,IGNORECASE class mainWindow(wxFrame): def __init__(self,parent,id,title): wxFrame.__init__(self,parent,-1,title,size=(500,200), style=wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE) self.mainPanel=wxPanel(self,-1) # create controls to be subsequently associated with accelerator keys self.dateEdit=wxTextCtrl(self.mainPanel,wxNewId(),'',(100,20)) self.comboBox=wxComboBox(self.mainPanel,wxNewId() ,'',(100,40),(-1,-1),[],wxCB_DROPDOWN) self.activityEdit=wxTextCtrl(self.mainPanel,wxNewId(),'',(100,60)) self.hoursEdit=wxTextCtrl(self.mainPanel,wxNewId(),'',(100,80)) self.visitedBox=wxCheckBox(self.mainPanel,wxNewId(),'',(100,100)) # instance a class that accummulates information about controls and accelerators accumAcceleratorTable=self.AccumAcceleratorTable(self,self.focusHandler) # as each label is created associate appropriate accelerator key with a control dateEditLabel=wxStaticText(self.mainPanel,-1,accumAcceleratorTable ('&Date',self.dateEdit),(10,20)) clientEditLabel=wxStaticText(self.mainPanel,-1,accumAcceleratorTable ('&Client',self.comboBox),(10,40)) activityEditLabel=wxStaticText(self.mainPanel,-1,accumAcceleratorTable ('&Activity',self.activityEdit),(10,60)) hoursEditLabel=wxStaticText(self.mainPanel,-1,accumAcceleratorTable ('&Hours',self.hoursEdit),(10,80)) visitedEditLabel=wxStaticText(self.mainPanel,-1,accumAcceleratorTable ('&Visited',self.visitedBox),(10,100)) # put the accummulated accelerator table and associations to use self.SetAcceleratorTable(wxAcceleratorTable(accumAcceleratorTable.acceleratorTable)) self.idControlDict=accumAcceleratorTable.idControlDict self.Show(True) def focusHandler(self,event): self.idControlDict[event.GetId()].SetFocus() class AccumAcceleratorTable: def __init__(self,parent,focusHandler): self.acceleratorTable=[] self.idControlDict={ } self.patt=compile(r'&([a-z])',IGNORECASE) self.focusHandler=focusHandler self.parent=parent def __call__(self,labelText,controlToFocus): # find the accelerator key,if any,in the label result=self.patt.search(labelText) if result: anId=wxNewId() self.acceleratorTable.append(( wxACCEL_ALT,ord(result.group(1).upper()),anId)) self.idControlDict[anId]=controlToFocus EVT_MENU(self.parent,anId,self.focusHandler) return labelText class App(wxApp): def OnInit(self): frame=mainWindow(None,-1,"Associating labels with controls") self.SetTopWindow(frame) return True if __name__=="__main__": app=App(0) app.MainLoop() }}} === Comments === If you have comments or suggestions, please contact [[Bill Bell]].