1

I am trying to do a dynamic search function, where the user also can select multiple items in a list. If we consider this example (I added this part, selectmode=MULTIPLE):

from Tkinter import *

# First create application class   
class Application(Frame):

def __init__(self, master=None):
    Frame.__init__(self, master)

    self.pack()
    self.create_widgets()

# Create main GUI window
def create_widgets(self):
    self.search_var = StringVar()
    self.search_var.trace("w", self.update_list)
    self.entry = Entry(self, textvariable=self.search_var, width=13)
    self.lbox = Listbox(self,selectmode=MULTIPLE, width=45, height=15)

    self.entry.grid(row=0, column=0, padx=10, pady=3)
    self.lbox.grid(row=1, column=0, padx=10, pady=3)
    self.btn = ttk.Button(self, text="Select", command=self.Select)
    self.btn.grid(column=1, row=1) 

    # Function for updating the list/doing the search.
    # It needs to be called here to populate the listbox.
    self.update_list()

def update_list(self, *args):
    search_term = self.search_var.get()

    # Just a generic list to populate the listbox
    lbox_list = ['Adam', 'Lucy', 'Barry', 'Bob',
                 'James', 'Frank', 'Susan', 'Amanda', 'Christie']

    self.lbox.delete(0, END)

    for item in lbox_list:
            if search_term.lower() in item.lower():
                self.lbox.insert(END, item)

def Select(self):

    reslist = list()
    selecion = self.lbox.curselection()

    for i in selecion:
        entered = self.lbox.get(i)
        reslist.append(entered)

    print reslist 

root = Tk()
root.title('Filter Listbox Test')
app = Application(master=root)
print 'Starting mainloop()'
app.mainloop()

The search function works perfectly fine, however, once a search has been done and an item has been selected, the selections is not saved since the lbox.delete function is used in update_list. Is there a way to keep each item selected while using the search function?

  • I'd see [this](https://stackoverflow.com/questions/7616541/get-selected-item-in-listbox-and-call-another-function-storing-the-selected-for). – Nae Nov 30 '17 at 14:16
  • Thanks for the link, however, I understand how to bind the selections if i'm not using the search bar. But, I would like to search for Adam, select that item and then search for Lucy and then call on the selected items (both Adam and Lucy). However, since the list is dynamically updating and items are removed from the list this doesn't work. – user9015897 Nov 30 '17 at 15:12
  • you have to keep selected elements on list and use this list to filter result of searching. – furas Nov 30 '17 at 16:02
  • or maybe you should create function which let you search with `"OR"` - `"Adam OR Lucy"` or `"Adam | Lucy"` or simply `"Adam Lucy"`. You could use regex to seach. – furas Nov 30 '17 at 16:05
  • I'd append them into an attribute after selection tbh. – Nae Nov 30 '17 at 16:23

1 Answers1

0

This is what I came up with. I don't know if you need it anymore but I'll post it anyway. I've basically added code to set values as selected if they are in user selection list after the listbox is refreshed on a change in Entry widget, and to remove it from user selection if user deselects irrespective of what is currently in the listbox.

from tkinter import *

sel=list()

# First create application class
class Application(Frame):

    def __init__(self, master=None):
        Frame.__init__(self, master)

        self.pack()
        self.create_widgets()

    def CurSelet(self,evt):
        global sel
        temp=list()
        for i in self.lbox.curselection():
            temp.append(self.lbox.get(i))

        allitems=list()
        for i in range(self.lbox.size()):
            allitems.append(self.lbox.get(i))

        for i in sel:
            if i in allitems:
                if i not in temp:
                    sel.remove(i)

        for x in self.lbox.curselection():
            if self.lbox.get(x) not in sel:
                sel.append(self.lbox.get(x))

    def select(self):
        global sel
        s=', '.join(map(str,sel))
        self.cursel.set('Current Selection: '+s)

    # Create main GUI window
    def create_widgets(self):
        self.search_var = StringVar()
        self.search_var.trace("w", lambda name, index, mode: self.update_list())
        self.entry = Entry(self, textvariable=self.search_var, width=13)
        self.lbox = Listbox(self, selectmode=MULTIPLE,width=45, height=15)
        self.lbox.bind('<<ListboxSelect>>',self.CurSelet)

        self.entry.grid(row=0, column=0, padx=10, pady=3)
        self.lbox.grid(row=1, column=0, padx=10, pady=3)

        self.btn=Button(self,text='Okay', command=self.select, width=20)
        self.btn.grid(row=2,column=0, padx=10, pady=3)

        self.cursel=StringVar()
        self.lb1=Label(self,textvariable=self.cursel)
        self.lb1.grid(row=3,column=0,padx=10,pady=3)

        # Function for updating the list/doing the search.
        # It needs to be called here to populate the listbox.
        self.update_list()



    def update_list(self):
        global sel
        global l
        search_term = self.search_var.get()

        # Just a generic list to populate the listbox
        lbox_list = ['Adam', 'Lucy', 'Barry', 'Bob',
                     'James', 'Frank', 'Susan', 'Amanda', 'Christie']

        self.lbox.delete(0, END)

        for item in lbox_list:
                if search_term.lower() in item.lower():
                    self.lbox.insert(END, item)

        allitems=list()
        for i in range(self.lbox.size()):
            allitems.append(self.lbox.get(i))

        for i in sel:
            if i in allitems:
                self.lbox.select_set(self.lbox.get(0, "end").index(i))

root = Tk()
root.title('Filter Listbox Test')
Label(root, text='Search enabled').pack()
app = Application(master=root)
print('Starting mainloop()')
app.mainloop()
7oS
  • 31
  • 4