1

How would I go about adding a search function that searches for text in the text widget? * Search from user input

def openFile():
    global text
    artiststxt = tkinter.Tk()
    artiststxt.title('Artists')
    artiststxt.geometry('300x360')
    artiststxt.minsize(300,360)
    artiststxt.maxsize(500,360)
    file = open('Artists.txt','r', encoding='utf-8')
    lines = file.read()
    scrollbar = Scrollbar(artiststxt, jump = 1)
    text = Text(artiststxt, yscrollcommand = scrollbar.set)
    scrollbar.configure(command=text.yview)
    text.insert(INSERT, lines)
    text.config(font=('Fixedsys', 15), fg = 'darkblue', bg = 'lightgray')
    menu = tkinter.Menu(artiststxt,tearoff=0)
    menu.add_command(label='Save', command = saveFile)
    artiststxt.config(menu=menu)
    scrollbar.pack(side=RIGHT, fill=BOTH)
    text.pack()

EDIT: Okay, I found out how to search for text with this:

def get(event):
global searchent
text.tag_remove('found', '1.0', END)
s = searchent.get()
if s:
    idx = '1.0'
    while 1:
        idx = text.search(s, idx, nocase=1, stopindex=END)
        if not idx: break
        lastidx = '%s+%dc' % (idx, len(s))
        text.tag_add('found', idx, lastidx)
        idx = lastidx
    text.tag_config('found', foreground='red')
searchent.focus_set()

Now, let's say the searched text is down further. How do I make it so the scrollbar goes downwards to the searched text?

Brian Fuller
  • 386
  • 1
  • 3
  • 12
  • I wish scrollbars were built into the Text and ListBox objects. It would reduce the amount of code necessary to interact with and sync both the widget and the completely independent scrollbar objects. – bob-the-destroyer Feb 02 '14 at 05:56
  • 1
    @bob-the-destroyer There is the [scrolledtext](http://stackoverflow.com/a/13833338/1217270) compound widget (see the bottom section). – Honest Abe Feb 02 '14 at 08:10
  • @bob-the-destroyer: if it were built-in, it would save you about three lines of code. That's really not saving you much. – Bryan Oakley Feb 02 '14 at 13:46
  • A complete example of a class that adds a method to highlight a regular expression is here: http://stackoverflow.com/a/3781773/7432 – Bryan Oakley Feb 02 '14 at 13:54
  • @Honest Abe: I didn't know that already existed. Thanks. – bob-the-destroyer Feb 02 '14 at 21:22

2 Answers2

2

Okay, I figured it out. Took some time but well worth it.

First we make an entry box in the window and we bind it with the enter key and put a .get event

searchent.bind("<Return>", get)

When enter key is pressed, we go to def get(event):

def get(event):
global searchent 
text.tag_remove('found', '1.0', END)
s = searchent.get() # Grabs the text from the entry box
if s:
    idx = '1.0'
    while 1:
        idx = text.search(s, idx, nocase=1, stopindex=END)
        if not idx: break
        lastidx = '%s+%dc' % (idx, len(s))
        text.tag_add('found', idx, lastidx)
        idx = lastidx
        text.see(idx)  # Once found, the scrollbar automatically scrolls to the text
    text.tag_config('found', foreground='red')
searchent.focus_set()
Brian Fuller
  • 386
  • 1
  • 3
  • 12
1

I make this piece of code using your post Brian Fuller, I hope it will help you, as it helped me, and others too..

from tkinter import *
from tkinter import messagebox as MessageBox

search_list = list()
s = ""

def reset_list():
    if s != entry_widget_name.get():
        print(entry_widget_name.get())
        search_list.clear()
        text_widget_name.tag_remove(SEL, 1.0,"end-1c")

def search_words():
    reset_list()
    global search_list
    global s
    text_widget_name.focus_set()
    s = entry_widget_name.get()

    if s:
        if search_list == []:
            idx = "1.0"
        else:
            idx = search_list[-1]

        idx = text_widget_name.search(s, idx, nocase=1, stopindex=END)
        lastidx = '%s+%dc' % (idx, len(s))

        try:
            text_widget_name.tag_remove(SEL, 1.0,lastidx)
        except:
            pass

        try:
            text_widget_name.tag_add(SEL, idx, lastidx)
            counter_list = []
            counter_list = str(idx).split('.')      
            text_widget_name.mark_set("insert", "%d.%d" % (float(int(counter_list[0])), float(int(counter_list[1]))))
            text_widget_name.see(float(int(counter_list[0])))
            search_list.append(lastidx)
        except:
            MessageBox.showinfo("Search complete","No further matches")
            search_list.clear()
            text_widget_name.tag_remove(SEL, 1.0,"end-1c")

root = Tk()
root.geometry("540x460")

lbl_frame_entry = LabelFrame(root, text="Enter the text to search", padx=5, pady=5)
lbl_frame_entry.pack(padx=10, pady=5, fill="both")

entry_widget_name = Entry(lbl_frame_entry, width=50, justify = "left")
entry_widget_name.pack(fill="both")

lbl_frame_text = LabelFrame(root, text="Enter the text here", padx=5, pady=5, height=260)
lbl_frame_text.pack(padx=10, pady=5, fill="both", expand=True)

text_widget_name = Text(lbl_frame_text)
text_widget_name.pack(fill="both", expand=True)

scrollbar = Scrollbar(text_widget_name, orient="vertical", command=text_widget_name.yview, cursor="arrow")
scrollbar.pack(fill="y", side="right")
text_widget_name.config(yscrollcommand=scrollbar.set)

button_name = Button(root, text="Search", command=search_words, padx=5, pady=5)
button_name.pack()
root.mainloop()
nilsoviani
  • 344
  • 5
  • 16