[wxPython-users] ComboBox: Incorrect usage?
Frank Millman
frank at chagford.com
Thu Jul 26 06:49:26 PDT 2007
Steve Holden wrote:
>
> I was hoping to be able to code wxComboBox to allow me to
> enter text and look up possible selections in a database - a
> little like the AJAX-style pulldowns you see all over the web
> nowadays.
>
> This is my best effort so far, but clearing the control
> appears to leave the text empty, and if I put a value in the
> text the insertion point is set at the start of the text.
> Setting the insertion point by removing the comment marker
> from the last line seems to lead to a loop, repeatedly
> printing out the single entered character until the program
> eventually terminates with no further output.
>
> def OnCompanyChar(self, event):
> """Set combo dropdown to companies whose names match
> the combo text."""
> combo = self.FindWindowById(cmbCompany)
> txt = combo.GetValue()
> sql = "SELECT orgName, orgID from organization WHERE
> lower(orgName) LIKE %s ORDER BY orgName"
> self.curs.execute(sql, (txt + "%", ))
> vals = self.curs.fetchall()
> combo.Clear()
> combo.AppendItems([v[0] for v in vals])
> #combo.SetSelection(wx.NOT_FOUND)
> print txt
> combo.SetValue(txt)
> #combo.SetInsertionPoint(len(txt)-1)
>
> Attempts to debug the code with Wing tells me that an
> uncaught Win32 exception is being raised. I suspect I am
> doing something obviously wrong, but it isn't shrieking at me.
>
Hi Steve
I don't have a full answer, but I played around a bit and found a clue.
I assume you are using MSW, as the problem does not seem to arise with GTK2.
I found that calling combo.SetInsertionPoint(n) on MSW generates an EVT_TEXT
event - heaven only knows why. I assume your entire method is driven by
catching this event, therefore you end up in a loop.
You will see from the attached program that I work around it by setting a
flag, and skipping the event the second time if the flag is set. This is
totally non-portable, as with GTK2 this means that you skip every second
character, but it does explain what is happening.
The attached program is just doodling - it does not do much. If you get a
full working solution, please post a working example here - I would find it
interesting. In particular, how do you get the box to display its drop-down
as you type, so you can see which items are available. Every time I type a
character, the drop-down closes.
A small point - I found that instead of
combo.Clear()
combo.AppendItems([...])
you can just say
combo.SetItems([...])
It seems to do the same thing.
HTH
Frank Millman
-------------- next part --------------
#!/usr/bin/env python
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(360,240))
MyPanel(self)
class MyPanel(wx.Panel):
def __init__(self,frame):
wx.Panel.__init__(self,frame,-1)
data = ['Apples','Oranges','Pears','Bananas','Peaches']
combo = wx.ComboBox(self,-1,'',pos=(10,10),choices=data)
combo.Bind(wx.EVT_COMBOBOX,self.onComboBox)
combo.Bind(wx.EVT_TEXT,self.onComboText)
combo.Bind(wx.EVT_TEXT_ENTER,self.onComboEnter)
combo.Bind(wx.EVT_KILL_FOCUS,self.onComboLostFocus)
button = wx.Button(self,-1,'Change list',pos=(10,60))
button.Bind(wx.EVT_BUTTON,self.onButton)
combo.SetFocus()
self.combo = combo
self.data = data
self.inserted = False
def onComboBox(self,evt):
print evt.EventObject.Value
def onComboText(self,evt):
if self.inserted:
print 'INSERTED'
self.inserted = False
return
print evt.EventObject.Value
txt = evt.EventObject.Value
lng = len(txt)
data = [x[:-lng] for x in self.data]
self.combo.SetItems(data)
self.combo.Value = txt
self.inserted = True
self.combo.SetInsertionPoint(len(txt))
def onComboEnter(self,evt):
print evt.EventObject.Value
def onComboLostFocus(self,evt):
print evt.EventObject.Value
def onButton(self,evt):
# self.combo.SetSelection(wx.NOT_FOUND)
self.combo.Value = ''
data = ['Peas','Beans','Carrots','Tomatoes','Cauliflower']
self.combo.SetItems(data)
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, "Test ComboBox")
frame.CentreOnScreen()
frame.Show(True)
self.SetTopWindow(frame)
return True
app = MyApp(0) # Create an instance of the application class
app.MainLoop() # Tell it to start processing events
More information about the wxpython-users
mailing list