具有自动完成功能的 ComboBox wxPython
ComboBox with autocomplete wxPython
我想要一个具有自动完成功能的 ComboBox,因为我有一个包含 1000 多个项目的列表,并且希望能够 select 一个元素而不必遍历整个列表,只需ComboBox 中项目字符串的一部分。
我一直在四处寻找,这个问题已得到多次回答,我什至检查了以下 link 来自上一个问题的内容:
- Auto-Completion In wxPython wxComboBox
和另一个 link:
然而,当我尝试 运行 示例代码时,我总是得到错误:"module 'wx' has no attribute 'SimpleHtmlListBox'/'HtmlListBox' ".
错误的原因可能是什么?还有其他方法可以实现自动完成 ComboBox 吗?
我已经转换了你给的第一个link中的代码,使它在python 3,wxPython Phoenix中工作。添加了一些更改以使组合框更好地工作。第一个 comboBox 已经在 Mac OSX 中进行了测试。但是当我测试它时 Linux gtk+,它没有按预期工作所以我在第二行创建了一个解决方法,使用 TextCtrl 作为 comboBox 的过滤器。
import wx
class PromptingComboBox(wx.ComboBox) :
def __init__(self, parent, choices=[], style=0, **par):
wx.ComboBox.__init__(self, parent, wx.ID_ANY, style=style|wx.CB_DROPDOWN, choices=choices, **par)
self.choices = choices
self.Bind(wx.EVT_TEXT, self.OnText)
self.Bind(wx.EVT_KEY_DOWN, self.OnPress)
self.ignoreEvtText = False
self.deleteKey = False
def OnPress(self, event):
if event.GetKeyCode() == 8:
self.deleteKey = True
event.Skip()
def OnText(self, event):
currentText = event.GetString()
if self.ignoreEvtText:
self.ignoreEvtText = False
return
if self.deleteKey:
self.deleteKey = False
if self.preFound:
currentText = currentText[:-1]
self.preFound = False
for choice in self.choices :
if choice.startswith(currentText):
self.ignoreEvtText = True
self.SetValue(choice)
self.SetInsertionPoint(len(currentText))
self.SetTextSelection(len(currentText), len(choice))
self.preFound = True
break
class TrialPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, wx.ID_ANY)
choices = ['grandmother', 'grandfather', 'cousin', 'aunt', 'uncle', 'grandson', 'granddaughter']
for relative in ['mother', 'father', 'sister', 'brother', 'daughter', 'son']:
choices.extend(self.derivedRelatives(relative))
self.choices = choices = sorted(choices)
mainSizer = wx.FlexGridSizer(2, 2, 5, 10)
self.SetSizer(mainSizer)
mainSizer.Add(wx.StaticText(
self, -1, "Worked in Mac - python 3 - wx phoenix"))
cb1 = PromptingComboBox(self, choices=choices)
mainSizer.Add(cb1)
mainSizer.Add(wx.StaticText(self, -1, "Work arround in Linux-gtk"))
sizer2 = wx.BoxSizer(wx.HORIZONTAL)
mainSizer.Add(sizer2)
filterCtrl = wx.TextCtrl(self, -1, size=(150, -1))
filterCtrl.Bind(wx.EVT_TEXT, self.OnFilter)
sizer2.Add(filterCtrl)
self.cb2 = wx.ComboBox(self, -1, size=(150, -1), choices=choices)
sizer2.Add(self.cb2)
def derivedRelatives(self, relative):
return [relative, 'step' + relative, relative + '-in-law']
def OnFilter(self, event):
currentText = event.GetString().upper()
tmpChoices = [c for c in self.choices if c.startswith(currentText)]
if tmpChoices != []:
self.cb2.SetItems(tmpChoices)
self.cb2.SetValue(tmpChoices[0])
else:
self.cb2.SetValue('')
self.cb2.SetItems([])
if __name__ == '__main__':
app = wx.App(False)
frame = wx.Frame (None, -1, 'Demo PromptingComboBox Control and Work around',
size=(700, 400))
TrialPanel(frame)
frame.Show()
app.MainLoop()
我想要一个具有自动完成功能的 ComboBox,因为我有一个包含 1000 多个项目的列表,并且希望能够 select 一个元素而不必遍历整个列表,只需ComboBox 中项目字符串的一部分。
我一直在四处寻找,这个问题已得到多次回答,我什至检查了以下 link 来自上一个问题的内容:
- Auto-Completion In wxPython wxComboBox
和另一个 link:
然而,当我尝试 运行 示例代码时,我总是得到错误:"module 'wx' has no attribute 'SimpleHtmlListBox'/'HtmlListBox' ".
错误的原因可能是什么?还有其他方法可以实现自动完成 ComboBox 吗?
我已经转换了你给的第一个link中的代码,使它在python 3,wxPython Phoenix中工作。添加了一些更改以使组合框更好地工作。第一个 comboBox 已经在 Mac OSX 中进行了测试。但是当我测试它时 Linux gtk+,它没有按预期工作所以我在第二行创建了一个解决方法,使用 TextCtrl 作为 comboBox 的过滤器。
import wx
class PromptingComboBox(wx.ComboBox) :
def __init__(self, parent, choices=[], style=0, **par):
wx.ComboBox.__init__(self, parent, wx.ID_ANY, style=style|wx.CB_DROPDOWN, choices=choices, **par)
self.choices = choices
self.Bind(wx.EVT_TEXT, self.OnText)
self.Bind(wx.EVT_KEY_DOWN, self.OnPress)
self.ignoreEvtText = False
self.deleteKey = False
def OnPress(self, event):
if event.GetKeyCode() == 8:
self.deleteKey = True
event.Skip()
def OnText(self, event):
currentText = event.GetString()
if self.ignoreEvtText:
self.ignoreEvtText = False
return
if self.deleteKey:
self.deleteKey = False
if self.preFound:
currentText = currentText[:-1]
self.preFound = False
for choice in self.choices :
if choice.startswith(currentText):
self.ignoreEvtText = True
self.SetValue(choice)
self.SetInsertionPoint(len(currentText))
self.SetTextSelection(len(currentText), len(choice))
self.preFound = True
break
class TrialPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, wx.ID_ANY)
choices = ['grandmother', 'grandfather', 'cousin', 'aunt', 'uncle', 'grandson', 'granddaughter']
for relative in ['mother', 'father', 'sister', 'brother', 'daughter', 'son']:
choices.extend(self.derivedRelatives(relative))
self.choices = choices = sorted(choices)
mainSizer = wx.FlexGridSizer(2, 2, 5, 10)
self.SetSizer(mainSizer)
mainSizer.Add(wx.StaticText(
self, -1, "Worked in Mac - python 3 - wx phoenix"))
cb1 = PromptingComboBox(self, choices=choices)
mainSizer.Add(cb1)
mainSizer.Add(wx.StaticText(self, -1, "Work arround in Linux-gtk"))
sizer2 = wx.BoxSizer(wx.HORIZONTAL)
mainSizer.Add(sizer2)
filterCtrl = wx.TextCtrl(self, -1, size=(150, -1))
filterCtrl.Bind(wx.EVT_TEXT, self.OnFilter)
sizer2.Add(filterCtrl)
self.cb2 = wx.ComboBox(self, -1, size=(150, -1), choices=choices)
sizer2.Add(self.cb2)
def derivedRelatives(self, relative):
return [relative, 'step' + relative, relative + '-in-law']
def OnFilter(self, event):
currentText = event.GetString().upper()
tmpChoices = [c for c in self.choices if c.startswith(currentText)]
if tmpChoices != []:
self.cb2.SetItems(tmpChoices)
self.cb2.SetValue(tmpChoices[0])
else:
self.cb2.SetValue('')
self.cb2.SetItems([])
if __name__ == '__main__':
app = wx.App(False)
frame = wx.Frame (None, -1, 'Demo PromptingComboBox Control and Work around',
size=(700, 400))
TrialPanel(frame)
frame.Show()
app.MainLoop()