2011-08-14 20 views
5

はあなたの誰もが、以下を可能にする方法の例を持っている:wxPythonを - dynamially textctrlに入力に応じて、listctrlを更新

私は> 600個の項目が表示さlistctrlを持っています。今、これらの項目を検索して、ユーザーがこの文字列を含む項目のみを表示するようにリストを更新するテキストを検索する必要があります。

リストに「Hello」、「Hi」、「Morning」が含まれているとします。リストには3つの項目がすべて表示されます。ユーザーはtextctrlに "h"と入力し、listctrlは "Hello"と "Hi"に絞り込まれます。ユーザーが代わりに "o"と入力すると、リストは "Hello"と "Morning"になります。

これは可能ですか?または、listctrl内の項目を見つける他の便利な方法はありますか?そして私の場合には、これは本当にケースではありません...

おかげで、Woodpicker

答えて

4

- あなたは正確にあなたが検索するのか分からない場合のみ、実際の利用である「あなたが入力すると、見つける」でのビルドwxPythonデモにはかなり良い "先行型"フィルタが組み込まれています。 source code to Main.pyを見ると、彼らはそれを「手動で」行い、ループしてリストを再構築します。彼らは、ツリービューを使用しているが、アイデアが健全である:

def OnSearch(self, event=None): 

    value = self.filter.GetValue() 
    if not value: 
     self.RecreateTree() 
     return 

    wx.BeginBusyCursor() 

    for category, items in _treeList: 
     self.searchItems[category] = [] 
     for childItem in items: 
      if SearchDemo(childItem, value): 
       self.searchItems[category].append(childItem) 

    wx.EndBusyCursor() 
    self.RecreateTree()  
+0

「Main.py」へのハイパーリンクが壊れています。 http://svn.wxwidgets.org/svn/wx/wxPython/trunk/demo/Main.py?view=markupそして、wxPythonがgithubに移動したので、ここに最新のリンクがあります(2017-12-07)。 https://github.com/wxWidgets/wxPython/blob/master/demo/Main.py – IceArdor

3

私はストレートwx.ListCtrlよりも優れObjectListViewラッパーが好き。ウィジェットの機能として、コントロール内の項目をフィルタリングする機能が含まれています。ここでそれについて読むことができます:http://objectlistview.sourceforge.net/python/features.html#filteringとここにコントロールのメインページです:http://objectlistview.sourceforge.net/python/

+0

知っておきたいことです。残念ながらこの特定のプロジェクトでは、私は貢献しているだけなので、既存のlistctrlで作業する必要があります。 – Woodpicker

+1

ObjectListViewは基本的にListCtrlのラッパーですから、ソースコードを見てみることもできます。それから彼の方法を再現することができます。 –

1

ここでは、UltimateListCtrlをフィルタリングする例です。 私はこれが2年後であることを知っていますが、私はstackoverflow上の他の例を見つけました。本当に役に立ちました。 私はpython/wxpythonの新機能ですが、うまくいけば便利です。 http://www.blog.pythonlibrary.org/2011/11/02/wxpython-an-intro-to-the-ultimatelistctrl/

import wx 
from wx.lib.agw import ultimatelistctrl as ULC 


class ULC_Panel(wx.Panel): 
    """""" 
    def __init__(self, parent, col_headers=None, list_data=None, options=None, dlg=None, 
      selected_list=None): 
     """Constructor""" 
     wx.Panel.__init__(self, parent) 
     self.options = options 
     self.show_only_selected = False 
     self.filter_string = "" 

     hsizer = wx.BoxSizer(wx.HORIZONTAL) 
     okayButton = wx.Button(self, wx.ID_OK, "OK") 
     okayButton.SetToolTip(wx.ToolTip("Click to close this dialog and use the selections")) 
     self.Bind(wx.EVT_BUTTON, self.OnOkayCanButton, okayButton) 
     hsizer.Add(okayButton, 0, wx.ALL, 5) 
     canButton = wx.Button(self, wx.ID_CANCEL, "Cancel") 
     canButton.SetToolTip(wx.ToolTip("Click to close this dialog and cancel selections")) 
     self.Bind(wx.EVT_BUTTON, self.OnOkayCanButton, canButton) 
     hsizer.Add(canButton, 0, wx.ALL, 5) 
     cb_show_only = wx.CheckBox(self, -1, "Show only selected items?") 
     cb_show_only.SetValue(self.show_only_selected) 
     cb_show_only.SetToolTip(wx.ToolTip("Click to show only selected rows")) 
     self.Bind(wx.EVT_CHECKBOX, self.EvtShowOnly, cb_show_only) 
     hsizer.Add(cb_show_only, 0, wx.ALL, 5) 

     self.stext = wx.StaticText(self, -1, "Filter: ", style=wx.ALIGN_LEFT) 
     self.filtr = wx.TextCtrl(self, -1, "", style=wx.ALIGN_LEFT) 
     self.Bind(wx.EVT_TEXT, self.OnFiltr, self.filtr) 
     fsizer = wx.BoxSizer(wx.HORIZONTAL) 
     fsizer.Add(self.stext, 0, wx.ALL) 
     fsizer.Add(self.filtr, 1, wx.EXPAND) 

     font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) 
     boldfont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) 
     boldfont.SetWeight(wx.BOLD) 
     boldfont.SetPointSize(12) 

     self.ultimateList = ULC.UltimateListCtrl(self, agwStyle = wx.LC_REPORT 
             | wx.LC_VRULES | ULC.ULC_HAS_VARIABLE_ROW_HEIGHT 
             | wx.LC_HRULES) 


     self.checkbox = [None] * len(list_data) 
     if selected_list != None: 
      self.selected = selected_list 
     else: 
      self.selected = [False] * len(list_data) 
     self.rows_max = len(list_data) 
     self.rows_current = -1 
     self.cols_max = len(col_headers) 
     self.cols_extra = 1 
     if options & ULC.ULC_MASK_CHECK: 
      self.cols_extra += 1 
     for i in xrange(self.cols_max+self.cols_extra): 
      info = ULC.UltimateListItem() 
      info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT 
      info._image = [] 
      info._format = 0 
      info._kind = 1 
      width = 150 
      if i >= self.cols_extra: 
       info._text = col_headers[i-self.cols_extra] 
      elif i == 0: 
       info._text = "Row" 
       width = 35 
      elif i == 1 and options & ULC.ULC_MASK_CHECK: 
       info._text = "Select" 
       width = 50 
      self.ultimateList.InsertColumnInfo(i, info) 
      self.ultimateList.SetColumnWidth(i, width) 

     self.list_data = list_data 
     pos = self.populate_table("") 

     if pos != None: 
      self.sz = self.ultimateList.GetItemRect(pos) 
      self.width = self.sz[2] + self.sz[3] 
      self.height = self.sz[1] 

     sizer = wx.BoxSizer(wx.VERTICAL) 
     sizer.Add(hsizer, 0, wx.EXPAND) 
     sizer.Add(fsizer, 0, wx.EXPAND) 
     sizer.Add(self.ultimateList, 1, flag=wx.EXPAND) 

     self.SetSizer(sizer) 
     sizer.Fit(self) 

    def EvtShowOnly(self, event): 
     cb = event.GetEventObject() 
     val = cb.GetValue() 
     self.show_only_selected = val 
     pos = self.populate_table(self.filter_string) 
     print "show_only_selected val= ", val 

    def EvtCheckBox(self, event): 
     cb = event.GetEventObject() 
     id = event.GetId() 
     val = cb.GetValue() 
     self.selected[id] = val 
     print "id, val= ", id, val 

    def OnOkayCanButton(self, event): 
     id = event.GetId() 
     dlg.EndModal(id) 

    def myGetNeedWH(self): 
     return (self.width, self.height) 

    def myGetSelectedState(self): 
     return self.selected 

    def populate_table(self, str_in): 
     busy = wx.BusyCursor() 
     if str_in: 
      str_low = str_in.lower() 
     if self.options & ULC.ULC_MASK_CHECK: 
      # if we have widgets in the row then we have to delete 1 row 
      # at a time (or else it leaves some of the widgets) 
      i = self.rows_current 
      #print "i, self.rows_max= ", i, self.rows_max 
      while i >= 0: 
       #print "i= ", i 
       self.ultimateList.DeleteItem(i) 
       i -= 1 
     else: 
      self.ultimateList.DeleteAllItems() 
     row = -1 
     for i in xrange(len(self.list_data)): 
      tlwr = self.list_data[i][0].lower() 
      if not str_in or tlwr.find(str_low) >= 0: 
       if self.show_only_selected and self.selected[i] == False: 
        continue 
       row += 1 
       for j in xrange(self.cols_max+self.cols_extra): 
        if j == 0: 
         pos = self.ultimateList.InsertStringItem(row, str(row)) 
        elif j == 1 and self.options & ULC.ULC_MASK_CHECK: 
         self.checkbox[i] = wx.CheckBox(self.ultimateList, id= i) 
         self.checkbox[i].SetValue(self.selected[i]) 
         self.checkbox[i].SetToolTip(wx.ToolTip("Click to select this row")) 
         self.Bind(wx.EVT_CHECKBOX, self.EvtCheckBox, self.checkbox[i]) 
         self.ultimateList.SetItemWindow(pos, col=1, wnd=self.checkbox[i], expand=False) 
        else: 
         self.ultimateList.SetStringItem(row, j, self.list_data[i][j-self.cols_extra]) 
     self.rows_current = row 
     return row 

    def OnFiltr(self, event): 
     str1 = event.GetString() 
     id = event.GetId() 
     #print "got txt_tval str[%s]= %s" % (id, str1) 
     self.filter_string = str1 
     pos = self.populate_table(str1) 
     event.Skip() 
     return 


######################################################################## 
class FilterListDiag(wx.Dialog): 
    def __init__(self, parent, id, title, headers=None, data_table=None, options=None, selected_list=None): 
     wx.Dialog.__init__(self, parent, id, title="", style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER) 
     options_in = options 

     self.panel = ULC_Panel(self, col_headers=headers, list_data=data_table, options=options_in, 
       dlg=self, selected_list=selected_list) 
     sizer = wx.BoxSizer(wx.VERTICAL) 
     sizer.Add(self.panel, 1, wx.EXPAND) 
     self.SetSizer(sizer) 
     (self.width, self.height) = self.panel.myGetNeedWH() 

    def myGetNeedWH(self): 
     return (self.width, self.height) 

    def myGetSelectedState(self): 
     return self.panel.myGetSelectedState() 

class TestFrame(wx.Frame): 
    def __init__(self): 
     """Constructor""" 
     wx.Frame.__init__(self, None, title="MvP UltimateListCtrl Demo", size=(850,600)) 

#---------------------------------------------------------------------- 
if __name__ == "__main__": 
    app = wx.App(False) 
    frame = TestFrame() 
    col_headers = ['col0', 'col1', 'col2'] 
    list_data = [ 
      ["Newsboys", "Go", "Rock"], 
      ["Puffy", "Bring It!", "Pop"], 
      ["Family Force 5", "III", "Pop"], 
      ["Me2", "III", "Pop"], 
      ["Duffy", "III", "Pop"], 
      ["Fluffy", "III", "Pop"], 
    ] 
    # sel_data passes in a list of which rows are already selected 
    sel_data = [ 
      False, 
      False, 
      False, 
      False, 
      True, 
      False, 
    ] 
    opt=ULC.ULC_MASK_CHECK # just reusing this to indicate I want a column of checkboxes. 
    dlg = FilterListDiag(frame, -1, "hi", headers=col_headers, data_table=list_data, options=opt, selected_list=sel_data) 
    (w, h) = dlg.myGetNeedWH() 
    print w,h 
    dlg.SetSizeWH(w, 300) 
    val = dlg.ShowModal() 
    selected = dlg.myGetSelectedState() 
    print "okay, can, val= ", wx.ID_OK, wx.ID_CANCEL, val 
    dlg.Destroy() 
    print 'selected=', selected 
関連する問題