python用wxpython的combobox怎么能让在它里面输入字符的时候,下拉列表自动给出含有该字符的可选列表?

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的选项,随着输入的增多,下面的选项越来越精确。这个怎么搞?望改善。财富值已加倍

温馨提示:答案为网友推荐,仅供参考
第1个回答  2023-04-28
可以使用`wx.ComboBox`的`AutoComplete`方法来实现这个功能。具体步骤如下:
1. 创建一个`wx.ComboBox`对象。

```

combo_box = wx.ComboBox(parent, id=wx.ID_ANY, choices=['apple', 'orange', 'banana'], style=wx.CB_DROPDOWN)
```
2. 调用`wx.ComboBox`的`AutoComplete`方法开启自动完成。

```

combo_box.AutoComplete([])
```
3. 将需要自动完成的可选列表传入`AutoComplete`方法。

```

combo_box.AutoComplete(['apple', 'orange', 'banana'])
```
这样,在`wx.ComboBox`中输入字符时,下拉列表会自动给出含有该字符的可选列表。完整的示例代码如下:

```

import wx
class MyFrame(wx.Frame):

def __init__(self, parent):
wx.Frame.__init__(self, parent, title='ComboBox Demo')
self.panel = wx.Panel(self)
self.combo_box = wx.ComboBox(self.panel, id=wx.ID_ANY, choices=['apple', 'orange', 'banana'], style=wx.CB_DROPDOWN)
self.combo_box.AutoComplete(['apple', 'orange', 'banana'])
if __name__ == '__main__':

app = wx.App()
frame = MyFrame(None)
frame.Show()
app.MainLoop()
```
运行该代码,可以看到在`wx.ComboBox`中输入字符时,下拉列表会自动给出含有该字符的可选列表。

亲!如果觉得我的答案对你有帮助,请采纳关注我哟,带你了解更多!
第2个回答  2023-04-28

在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控件的可选项,实际应用中还需要考虑更多的细节问题,例如数据源的更新和异常处理等。