古詩詞大全網 - 古詩大全 - 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會根據輸入值過濾選項並顯示正確的選項。