This recipe offers a wxComboBox subclass that will display the first entire item from its dropdown list whose initial characters match those that the user has typed, with untyped characters selected.

What Objects are Involved

Only wx.ComboBox itself.

Process Overview

When the user keys a 'c', for instance, we want the code to identify the first combobox choice that begins with 'c', and to display it in the combobox with the characters following 'c' "selected". One does this in response to the wx.EVT_TEXT event. When one changes the content of the combobox, however, this ellicits another wx.EVT_TEXT event and this leads to infinite recursion.

To prevent this we arrange to ignore the second wx.EVT_TEXT that is ellicited.

Similar code is used to make it possible for the control to respond properly to backspaces, and when the user selects a choice from the dropdown list.

Special Concerns

The code in the loop in the wx.EVT_TEXT handler might well be changed so that the combobox would accept plugins providing different suggestion options; for example, the most frequently selected option could be offered.

Code Sample

   1 import wx
   3 class PromptingComboBox(wx.ComboBox) :
   4     def __init__(self, parent, value, choices=[], style=0, **par):
   5         wx.ComboBox.__init__(self, parent, wx.ID_ANY, value, style=style|wx.CB_DROPDOWN, choices=choices, **par)
   6         self.choices = choices
   7         self.Bind(wx.EVT_TEXT, self.EvtText)
   8         self.Bind(wx.EVT_CHAR, self.EvtChar)
   9         self.Bind(wx.EVT_COMBOBOX, self.EvtCombobox) 
  10         self.ignoreEvtText = False
  12     def EvtCombobox(self, event):
  13         self.ignoreEvtText = True
  14         event.Skip()
  16     def EvtChar(self, event):
  17         if event.GetKeyCode() == 8:
  18             self.ignoreEvtText = True
  19         event.Skip()
  21     def EvtText(self, event):
  22         if self.ignoreEvtText:
  23             self.ignoreEvtText = False
  24             return
  25         currentText = event.GetString()
  26         found = False
  27         for choice in self.choices :
  28             if choice.startswith(currentText):
  29                 self.ignoreEvtText = True
  30                 self.SetValue(choice)
  31                 self.SetInsertionPoint(len(currentText))
  32                 self.SetMark(len(currentText), len(choice))
  33                 found = True
  34                 break
  35         if not found:
  36             event.Skip()
  38 class TrialPanel(wx.Panel):
  39     def __init__(self, parent):
  40         wx.Panel.__init__(self, parent, wx.ID_ANY)
  42         choices = ['grandmother', 'grandfather', 'cousin', 'aunt', 'uncle', 'grandson', 'granddaughter']
  43         for relative in ['mother', 'father', 'sister', 'brother', 'daughter', 'son']:
  44             choices.extend(self.derivedRelatives(relative))
  46         cb = PromptingComboBox(self, "default value", choices, style=wx.CB_SORT) 
  48     def derivedRelatives(self, relative):
  49         return [relative, 'step' + relative, relative + '-in-law']
  52 if __name__ == '__main__':
  53     app = wx.App()
  54     frame = wx.Frame (None, -1, 'Demo PromptingComboBox Control', size=(400, 50))
  55     TrialPanel(frame)
  56     frame.Show()
  57     app.MainLoop()


Any comments or suggestions, to Bill Bell, please.

Combo Box that Suggests Options (last edited 2008-03-11 10:50:26 by localhost)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.