Search code examples
pythontkintertkinter-text

how to update the index to scroll to each found word in a text box widget?


I need to consequently find each matching word add scroll to it in the text box with a button click. This function only finds the first matching word. How can I feed the updated index to a function that is bound to the button?

def find(idx='1.0'):
    text.tag_remove('found', idx, END)
    s = edit.get()
    if s:
        idx = text.search(s, idx, nocase=1,
                          stopindex=END)
        if not idx:
            return None
  
        foundidx = '%s+%dc' % (idx, len(s))

        text.tag_add('found', idx, foundidx)
        text.see(foundidx)

        text.tag_config('found', foreground='red')
        edit.focus_set()

    return foundidx

Solution

  • To achive this you need a Text widget and a root that display via widget a example text. I did it with this:

    import tkinter as tk
    
    root = tk.Tk()
    
    text = tk.Text(root)
    text.pack()
    text.insert('1.0','''
    Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
    sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
    sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
    no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet,
    consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
    sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
    Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
    
    Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
    sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
    sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
    no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet,
    consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
    sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
    Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
    
    Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
    sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
    sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
    no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet,
    consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
    sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
    Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
    
    Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
    sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
    sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
    no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet,
    consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
    sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
    Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
    
    text by: https://www.loremipsum.de/
    ''')
    

    after this I followed the instructions of the link out of the comments. And extended it by saveing the positions and the index.

    countVar = tk.StringVar()
    idxVar = tk.StringVar()
    posis = []
    def search():
        try:
            if idxVar.get():
                new_idx = float(idxVar.get()+countVar.get())
                pos = text.search('sed', new_idx, 'end', count=countVar)
                text.tag_add('search', pos, '%s + %sc' % (pos, countVar.get()))
                text.tag_configure('search', background='green')
                idxVar.set(pos)
                posis.append(pos)
            else:
                pos = text.search('sed', '1.0', 'end', count=countVar)
                text.tag_add('search', pos, '%s + %sc' % (pos, countVar.get()))
                text.tag_configure('search', background='green')
                idxVar.set(pos)
                posis.append(pos)
        except:
            idxVar.set('1.0')
    
    button = tk.Button(root,text='search',command=search)
    button.pack()
    

    At least I used the Text.see method to jump to the points of my posis list:

    show = tk.IntVar()
    show.set(0)
    
    def see():
        if show.get() <= len(posis)-1:
            pos = show.get()
            text.see(posis[show.get()])
            show.set(pos+1)
        else:
            show.set(0)
            
    
    button2= tk.Button(root,text='see', command=see)
    button2.pack()
    
    root.mainloop()
    

    I know this code can be improved by a lot, but it should show the priciple and I used to code it self explanatory. But if there are open questions, let me know and I improve this answer.