#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2013
    Location
    California, USA
    Posts
    76
    Rep Power
    2

    Scrolling to Specific Listbox Item in Code


    You should see in the code example below that scrolling
    downward and highlighting the search target works pretty well.
    Then when I search for the item at the top of the list,
    the scrolling does not go fully to the top, then after one
    more search for item #1, it does scroll to the top.

    Looking for insights on how to get control of the upward scroll.

    Another subject that I find difficult to locate on the web:
    Can a listbox item be selected in code?

    Thanks
    Code:
    from tkinter import *
    
    root = Tk()
    
    root.geometry("320x350+20+20")
    root.title('Searchable Listbox with Scrollbar')
    
    class view_app:
        
        def __init__(self,root):
            
            self.frame = Frame(root, borderwidth=1, relief=GROOVE)
            self.frame.pack()
            self.frame.place(x=50, y=80)
            
            self.listbox = Listbox(self.frame, font=('Courier', 12),
                width=20, height=10)
            self.listbox.pack(side=LEFT, fill=Y)
    
            #create a vertical scrollbar to the right of the listbox
            self.yscroll = Scrollbar(self.frame, command=self.listbox.yview, orient=VERTICAL)
            self.yscroll.pack(side=RIGHT, fill=Y)
            
            self.listbox.configure(yscrollcommand=self.yscroll.set)
    
            list_contents = ['eggs', 'spam', 'corn', 'milk', 'beans', 'bread',
                             'rice', 'cheese', 'grapes', 'beef', 'tuna', 'bacon']
    
            for n in range(0, len(list_contents)):
                self.listbox.insert('end', list_contents[n])
    
            instrLabel = Label(root, text="Type in search word and press Enter")
            instrLabel.pack(side=TOP)
            
            self.eVar = StringVar()
            self.e = Entry(root, textvariable=self.eVar, width = 12)
            self.e.config(font=('Helvetica', 16))
            self.e.pack(side=TOP)
            self.e.bind('<Return>', self.find_word)
            self.e.focus()
            
            self.m1 = StringVar()
            self.msg1 = Label(root, textvariable=self.m1, width = 16)
            self.msg1.pack(side=TOP)    
    
        def find_word(self, event):
            """
            search listbox to locate word entered.
            highlight word if found, give message of found or not
            found.
            """
    
            found_index = -1
            target = self.e.get()
            self.m1.set('')     #clear message of previous search results
    
            if len(target) > 0:
                targetLcase = target.lower()
                for n in range(0, self.listbox.size()):
                    if targetLcase == self.listbox.get(n).lower():
                        found_index = n
                        break
                
                if found_index != -1:
                    found_index -= 1
            
                    self.listbox.yview_scroll(found_index, 'units')
    
                    for r in range(0, self.listbox.size()):   #clear previous highlight
                        self.listbox.itemconfig(r, bg='white')
    
                    self.listbox.itemconfig(found_index+1, bg='Azure')  #highlight found target 
                    self.m1.set(target + ' found')
                else:
                    self.m1.set(target + ' not found')    
    
                self.e.delete(0, END)
    
                
    app = view_app(root)
            
    root.mainloop()
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    May 2009
    Posts
    510
    Rep Power
    33
    You possibly want listbox.see() or yscroll.set() depending on what you want to do. The following modified code uses see() to adjust the part of the listbox that is visible-the selected item is always visible, and uses get() to show what the parameters would be to use set() to move the y slider.
    Code:
    from tkinter import *
    
    root = Tk()
    
    root.geometry("320x350+20+20")
    root.title('Searchable Listbox with Scrollbar')
    
    class view_app:
        
        def __init__(self,root):
            
            self.frame = Frame(root, borderwidth=1, relief=GROOVE)
            self.frame.pack()
            self.frame.place(x=50, y=80)
            
            self.listbox = Listbox(self.frame, font=('Courier', 12),
                width=20, height=10)
            self.listbox.pack(side=LEFT, fill=Y)
    
            #create a vertical scrollbar to the right of the listbox
            self.yscroll = Scrollbar(self.frame, command=self.listbox.yview, orient=VERTICAL)
            self.yscroll.pack(side=RIGHT, fill=Y)
            
            self.listbox.configure(yscrollcommand=self.yscroll.set)
    
            list_contents = ['eggs', 'spam', 'corn', 'milk', 'beans', 'bread',
                             'rice', 'cheese', 'grapes', 'beef', 'tuna', 'bacon']
    
            for n in range(0, len(list_contents)):
                self.listbox.insert('end', list_contents[n])
    
            instrLabel = Label(root, text="Type in search word and press Enter")
            instrLabel.pack(side=TOP)
            
            self.eVar = StringVar()
            self.e = Entry(root, textvariable=self.eVar, width = 12)
            self.e.config(font=('Helvetica', 16))
            self.e.pack(side=TOP)
            self.e.bind('<Return>', self.find_word)
            self.e.focus()
            
            self.m1 = StringVar()
            self.msg1 = Label(root, textvariable=self.m1, width = 16)
            self.msg1.pack(side=TOP)    
    
        def find_word(self, event):
            """
            search listbox to locate word entered.
            highlight word if found, give message of found or not
            found.
            """
    
            found_index = -1
            target = self.e.get()
            self.m1.set('')     #clear message of previous search results
    
            if len(target) > 0:
                targetLcase = target.lower()
                for n in range(0, self.listbox.size()):
                    if targetLcase == self.listbox.get(n).lower():
                        found_index = n
                        break
                
                if found_index != -1:
                    self.listbox.see(found_index)
                    print(self.yscroll.get())
                    found_index -= 1
            
    ##                self.listbox.yview_scroll(found_index, 'units')
    
                    for r in range(0, self.listbox.size()):   #clear previous highlight
                        self.listbox.itemconfig(r, bg='white')
    
                    self.listbox.itemconfig(found_index+1, bg='Azure')  #highlight found target 
                    self.m1.set(target + ' found')
                else:
                    self.m1.set(target + ' not found')    
    
                self.e.delete(0, END)
    
                
    app = view_app(root)
            
    root.mainloop()
    Last edited by dwblas; September 4th, 2013 at 09:23 PM.

IMN logo majestic logo threadwatch logo seochat tools logo