Sudarshan
Sudarshan

Reputation: 11

Wxpython Filter dropdown not working in latest version 4.1.1 same example working with 4.0.7 version

When assigning the value to combobox in event it will fire again same event and program goes in infinite loop. however same code working in wxpython version 4.0.7. correct me if I am doing something wrong.

import wx      
    class Mywin(wx.Frame):
        def __init__(self, parent: object, title: object) -> object:
            super(Mywin, self).__init__(parent, title=title, size=(300, 200))
            self.languages = ['C', 'C++', 'Python', 'Java', 'Perl']
    
            panel = wx.Panel(self)
            box = wx.BoxSizer(wx.VERTICAL)
    
            self.label = wx.StaticText(panel, label="Your choice:", style=wx.ALIGN_CENTRE)
            box.Add(self.label, 0, wx.EXPAND | wx.ALL, 20)
    
            cblbl = wx.StaticText(panel, label="Combo box", style=wx.ALIGN_CENTRE)
            box.Add(cblbl, 0, wx.EXPAND | wx.ALL, 5)
    
            self.combo = wx.ComboBox(panel, choices=self.languages)
            box.Add(self.combo, 1, wx.EXPAND | wx.ALL, 5)
    
            box.AddStretchSpacer()
            self.combo.Bind(wx.EVT_TEXT, self.oncombo)
            self.ignoreEvtText = False
    
            panel.SetSizer(box)
            self.Centre()
            self.Show()
    
        def oncombo(self, event):
    
            if self.ignoreEvtText:
                self.ignoreEvtText = False
                return
    
            textEntered = event.GetString()
    
            self.label.SetLabel("You selected" + self.combo.GetValue() + " from Combobox" + textEntered)
    
            if textEntered:
                self.ignoreEvtText = True
                matching = [s for s in self.languages if textEntered in s]
                self.combo.Set(matching)
                self.combo.SetInsertionPoint(len(textEntered))
                self.combo.SetValue(textEntered)
            else:
                self.combo.Set(self.languages)
    
            self.combo.Popup()
    
    
    app = wx.App()
    Mywin(None, 'ComboBox and Choice demo')
    app.MainLoop()

Upvotes: 0

Views: 141

Answers (2)

Kemp
Kemp

Reputation: 3649

I couldn't find a clear answer regarding the infinite loop anywhere else so I did a little investigation of my own.

It appears that an EVT_TEXT is fired as a result of the call to Set as well the call to SetValue. This means that you have to do:

self.ignoreEvtText = True
self.Set(matching)
self.ignoreEvtText = True
self.SetValue(textEntered)
self.combo.SetInsertionPoint(len(textEntered))

to avoid creating the infinite loop of events. The call to SetInsertionPoint has to move after the call to SetValue also, otherwise the text isn't there for the insertion point to be set correctly.

As a final note the call to Popup causes very odd results, at least for me on the latest wxPython on Windows 11. In particular, an annoying delay after each character while the dropdown animation plays again, and the text being highlighted and then immediately un-highlighted. Additionally there were cases where losing focus would cause the dropdown to go into a disappear-reappear loop drawn on top of the application that now had focus. As a result I've ended up not using that. The user can open the dropdown themself and avoid the weirdness.

Upvotes: 0

Rolf of Saxony
Rolf of Saxony

Reputation: 22448

Use:

self.combo.Bind(wx.EVT_COMBOBOX, self.oncombo)

rather than:

self.combo.Bind(wx.EVT_TEXT, self.oncombo)

EVT_TEXT causes you to drop into an continual event loop.

Each time the text changes, if fires the event, which changes the text, which fires the event, which ......

Upvotes: 0

Related Questions