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
1 from wxPython.wx import *
2
3 from re import compile,IGNORECASE
4
5 class mainWindow(wxFrame):
6 def __init__(self,parent,id,title):
7 wxFrame.__init__(self,parent,-1,title,size=(500,200),
8 style=wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
9
10 self.mainPanel=wxPanel(self,-1)
11
12 # create controls to be subsequently associated with accelerator keys
13 self.dateEdit=wxTextCtrl(self.mainPanel,wxNewId(),'',(100,20))
14 self.comboBox=wxComboBox(self.mainPanel,wxNewId() ,'',(100,40),(-1,-1),[],wxCB_DROPDOWN)
15 self.activityEdit=wxTextCtrl(self.mainPanel,wxNewId(),'',(100,60))
16 self.hoursEdit=wxTextCtrl(self.mainPanel,wxNewId(),'',(100,80))
17 self.visitedBox=wxCheckBox(self.mainPanel,wxNewId(),'',(100,100))
18
19 # instance a class that accummulates information about controls and accelerators
20 accumAcceleratorTable=self.AccumAcceleratorTable(self,self.focusHandler)
21
22 # as each label is created associate appropriate accelerator key with a control
23 dateEditLabel=wxStaticText(self.mainPanel,-1,accumAcceleratorTable ('&Date',self.dateEdit),(10,20))
24 clientEditLabel=wxStaticText(self.mainPanel,-1,accumAcceleratorTable ('&Client',self.comboBox),(10,40))
25 activityEditLabel=wxStaticText(self.mainPanel,-1,accumAcceleratorTable ('&Activity',self.activityEdit),(10,60))
26 hoursEditLabel=wxStaticText(self.mainPanel,-1,accumAcceleratorTable ('&Hours',self.hoursEdit),(10,80))
27 visitedEditLabel=wxStaticText(self.mainPanel,-1,accumAcceleratorTable ('&Visited',self.visitedBox),(10,100))
28
29 # put the accummulated accelerator table and associations to use
30 self.SetAcceleratorTable(wxAcceleratorTable(accumAcceleratorTable.acceleratorTable))
31 self.idControlDict=accumAcceleratorTable.idControlDict
32
33 self.Show(True)
34
35 def focusHandler(self,event):
36 self.idControlDict[event.GetId()].SetFocus()
37
38 class AccumAcceleratorTable:
39 def __init__(self,parent,focusHandler):
40 self.acceleratorTable=[]
41 self.idControlDict={ }
42 self.patt=compile(r'&([a-z])',IGNORECASE)
43 self.focusHandler=focusHandler
44 self.parent=parent
45
46 def __call__(self,labelText,controlToFocus):
47 # find the accelerator key,if any,in the label
48 result=self.patt.search(labelText)
49 if result:
50 anId=wxNewId()
51 self.acceleratorTable.append(( wxACCEL_ALT,ord(result.group(1).upper()),anId))
52 self.idControlDict[anId]=controlToFocus
53 EVT_MENU(self.parent,anId,self.focusHandler)
54 return labelText
55
56 class App(wxApp):
57 def OnInit(self):
58 frame=mainWindow(None,-1,"Associating labels with controls")
59 self.SetTopWindow(frame)
60 return True
61
62 if __name__=="__main__":
63 app=App(0)
64 app.MainLoop()
Comments
If you have comments or suggestions, please contact Bill Bell.