python用wxpython的combobox怎么能让在它里面输入字符的时候,下拉列表自动给出含有该字符的可选列表,列表中链接的数据已和数据空连接好。请给出代码示例: 实现类似下图效果
要实现这种自动补全的功能,可以使用wxPython中的wx.ComboBox控件,并自定义一个类来实现自动补全。以下是一个简单的代码示例:
import wx
class AutoCompleteComboBox(wx.ComboBox):
def __init__(self, *args, **kwargs):
super(AutoCompleteComboBox, self).__init__(*args, **kwargs)
self.choices = []
self.Bind(wx.EVT_TEXT, self.OnText)
self.Bind(wx.EVT_COMBOBOX, self.OnSelect)
def SetChoices(self, choices):
self.choices = choices
def OnText(self, event):
input_text = event.GetString()
if not input_text:
self.SetItems(self.choices)
return
filtered_choices = [choice for choice in self.choices if input_text.lower() in choice.lower()]
self.SetItems(filtered_choices)
self.Popup()
def OnSelect(self, event):
pass
class MyFrame(wx.Frame):
def __init__(self, parent, title):
super(MyFrame, self).__init__(parent, title=title, size=(400, 300))
panel = wx.Panel(self)
self.Bind(wx.EVT_CLOSE, self.OnClose)
choices = ["Apple", "Banana", "Cherry", "Date", "Fig", "Grape", "Kiwi", "Lemon", "Mango", "Orange"]
self.combo_box = AutoCompleteComboBox(panel, pos=(50, 50), size=(200, -1), choices=choices, style=wx.CB_DROPDOWN)
self.combo_box.SetChoices(choices)
def OnClose(self, event):
self.Destroy()
if __name__ == "__main__":
app = wx.App(False)
frame = MyFrame(None, "AutoComplete ComboBox Example")
frame.Show()
app.MainLoop()
在这个例子中,我们首先创建了一个AutoCompleteComboBox类,它继承自wx.ComboBox。我们为这个类添加了SetChoices方法,用于设置所有可能的选项。然后,我们通过监听wx.EVT_TEXT事件来监听输入框中文本的变化。当文本发生变化时,我们根据输入的文本筛选下拉列表中的选项,并显示筛选后的结果。
请注意,这个示例使用的数据是一个固定的字符串列表。如果您需要从数据库中获取数据,只需将choices替换为从数据库查询得到的结果。
…………
回复:
经过仔细检查,我发现在 OnText 方法中更新 ComboBox 项目时确实存在问题。当我们使用 SetItems 方法设置项目时,文本框内容会被清除,从而触发另一个 wx.EVT_TEXT 事件。因此,我们需要稍微修改 OnText 方法以避免无限递归。
以下是修复后的代码示例:
import wx
class AutoCompleteComboBox(wx.ComboBox):
def __init__(self, *args, **kwargs):
super(AutoCompleteComboBox, self).__init__(*args, **kwargs)
self.choices = []
self.Bind(wx.EVT_TEXT, self.OnText)
self.Bind(wx.EVT_COMBOBOX, self.OnSelect)
def SetChoices(self, choices):
self.choices = choices
def OnText(self, event):
input_text = event.GetString()
if not input_text:
self.SetItems(self.choices)
return
filtered_choices = [choice for choice in self.choices if input_text.lower() in choice.lower()]
# Avoid recursive call to OnText when setting items.
self.Unbind(wx.EVT_TEXT)
self.SetItems(filtered_choices)
self.Bind(wx.EVT_TEXT, self.OnText)
self.SetValue(input_text) # Reset the text value after updating items
self.SetInsertionPointEnd() # Move the cursor to the end of the text
self.Popup()
def OnSelect(self, event):
pass
# ... (the rest of the code remains unchanged)
这里的关键更改是在设置新项目之前取消绑定 wx.EVT_TEXT 事件,然后在设置项目后重新绑定事件。这样,在我们更新项目时就不会触发 OnText 方法。我们还使用 SetValue 方法重新设置文本值,并将光标移至文本末尾。
经过这些更改,代码应该可以正常运行,不会导致无限递归和不断增长的项目列表。
…………
回复:
以下是根据您的需求修改后的代码示例。主要的修改是在更新ComboBox项目后,使用ChangeValue方法而不是SetValue方法来设置文本值,以便在不触发EVT_TEXT事件的情况下更改文本值。
import wx
class AutoCompleteComboBox(wx.ComboBox):
def __init__(self, *args, **kwargs):
super(AutoCompleteComboBox, self).__init__(*args, **kwargs)
self.choices = []
self.Bind(wx.EVT_TEXT, self.OnText)
self.Bind(wx.EVT_COMBOBOX, self.OnSelect)
def SetChoices(self, choices):
self.choices = choices
def OnText(self, event):
input_text = event.GetString()
if not input_text:
self.SetItems(self.choices)
return
filtered_choices = [choice for choice in self.choices if input_text.lower() in choice.lower()]
# Avoid recursive call to OnText when setting items.
self.Unbind(wx.EVT_TEXT)
self.SetItems(filtered_choices)
self.Bind(wx.EVT_TEXT, self.OnText)
self.ChangeValue(input_text) # Set the text value without triggering EVT_TEXT
self.SetInsertionPointEnd() # Move the cursor to the end of the text
self.Popup()
def OnSelect(self, event):
pass
# ... (the rest of the code remains unchanged)
现在,使用ChangeValue方法更新输入值后,输入框中的文本将保持不变,您可以连续输入多个字符,ComboBox会根据输入值过滤选项并显示正确的选项。
文本框输入内容之后文本框就会刷新,下面的选项无法显示,应该是无限递归造成的,而且我发现每输入一次,列表就会刷新之后把原来的数据增加一次,长度也随着增加一次
追答见正文修订
追问但下拉框还会刷好几遍,注释掉ontext中self.SetInsertionPointEnd()、将self.SetValue()改为self.GetValue()后会随输入显示选项,下拉不乱刷了,但只能输一个字,且下拉框不显示输入的字符了,我要的效果是,输入a,出现带有a的选项,再a后面输入p,下面出现带有ap的选项,随着输入的增多,下面的选项越来越精确。这个怎么搞?望改善。财富值已加倍
在wxPython的ComboBox控件中,可以使用Bind()方法绑定EVT_TEXT事件来实现用户在ComboBox中输入字符时的响应操作。具体实现过程如下:
1.创建ComboBox控件,并将其绑定到EVT_TEXT事件:
import wx
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='ComboBox Example')
panel = wx.Panel(self)
self.combo = wx.ComboBox(panel, pos=(10, 10), size=(200, -1), style=wx.CB_DROPDOWN)
self.combo.Bind(wx.EVT_TEXT, self.onText)
def onText(self, event):
text = self.combo.GetValue()
# 在此处更新下拉列表的内容
2.在EVT_TEXT事件的回调函数onText()中获取用户输入的文本内容,并根据该内容更新下拉列表的可选项。可以通过调用ComboBox控件的Set()方法来更新下拉列表,其中第一个参数为可选项列表,第二个参数为默认选中的可选项索引。可选项列表应该是含有用户输入字符的可选项。
def onText(self, event):
text = self.combo.GetValue()
choices = [data for data in data_list if text in data] # data_list为可选项数据源
self.combo.Set(choices, 0)
这样,在ComboBox控件中输入字符时,就会自动更新下拉列表中的可选项。注意,这里只是演示如何动态更新ComboBox控件的可选项,实际应用中还需要考虑更多的细节问题,例如数据源的更新和异常处理等。