Tkinter:搜索时自动将滚动条移动到创建的项目

Tkinter: move scrollbar automatically to the founded item when searching

这是我的应用程序的一个小副本,我在其中使用 for 循环创建了许多文本小部件;我还创建了一个搜索条目和选项来突出显示文本小部件内的上下文,以便更容易找到正在查找的文本。我想知道是否有一种方法可以自动将滚动条移动到搜索到的文本:所以,如果我在我的应用程序的开头(数字 0 所在的位置)并在底部搜索一个数字(例如 81) 81 号码将突出显示,框架会自行下降以显示号码。这是我现在的代码:

class App(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)

        self.entry = tk.Entry(self, justify="center", width=6)
        self.entry.pack(padx=(15,0), ipady=5, side="top", anchor="e")

        button = tk.Button(self, text="Search", width=13, command=self.search)
        button.pack(side="top", anchor="e")   

        self.frame = tk.Frame(self)
        self.frame.pack(fill="both", expand="true", side="bottom")

        self.canvas = tk.Canvas(self.frame, highlightthickness=0)
        self.canvas.pack(side="left", fill="both", expand="true")
        self.canvas.bind_all("<MouseWheel>", self.on_mousewheel)    
    
        self.pop()


    def on_mousewheel(self, event):
        shift = (event.state & 0x1) != 0
        scroll = -1 if event.delta > 0 else 1
        if shift:
            self.canvas.xview_scroll(scroll, "units")
        else:
            self.canvas.yview_scroll(scroll, "units")


    def pop(self):    
        self.list = list(range(101))
        self.loop = []
     
        self.scrollbar = ttk.Scrollbar(self.frame, orient="vertical", command=self.canvas.yview)
        self.scrollbar.pack(side="right", fill="y")

        self.canvas.configure(yscrollcommand=self.scrollbar.set)
        self.canvas.bind('<Configure>', lambda e: self.canvas.configure(scrollregion = self.canvas.bbox("all")))

        self.list_frame = tk.Frame(self.canvas)

        self.canvas.create_window((0,0), window=self.list_frame, anchor="nw")

        for index, number in enumerate(self.list): 
            self.frame_2 = tk.Frame(self.list_frame)
            self.frame_2.pack(pady=(15,0), fill="x", expand="yes", side="top")

            self.text = tk.Text(self.frame_2, wrap="word", height=1)
            self.text.pack(padx=15, side="left")
            self.text.tag_configure("normal")
            self.text.insert("end", number, "normal")
            self.text.config(state="disabled")
            
            self.text.tag_configure("select", foreground="white", background="green")

            self.canc_button = tk.Button(self.frame_2, text="Cancel", command=lambda x=index: self.delete(x))
            self.canc_button.pack(side="right")

            self.loop.append((self.text, self.canc_button))


    def search(self):   
        self.found = self.entry.get()

        for self.text in self.loop:
            if self.found:
                self.text[0].tag_remove("select", 1.0,"end-1c")

                idx = '1.0'
                while 1:
                    idx = self.text[0].search(self.found, idx, nocase=1, stopindex="end")
                    if not idx: break

                    lastidx = f"{idx}+{int(len(self.found))}c"
                     
                    self.text[0].tag_add("select", idx, lastidx)

                    idx = lastidx 


if __name__ == "__main__":
    root = tk.Tk()
    App(root).pack(side="top", fill="both", expand=True)
    root.mainloop()

谢谢!

这对我有用:

在我更改的地方有评论,解释了添加的代码的作用

class App(tk.Frame):
    # (rest of code)

    def search(self):
        self.found = self.entry.get()
        
        # variable to store index of Label with found text
        scrollto = None

        for i, self.text in enumerate(self.loop):
            if self.found:

                self.text[0].tag_remove("select", 1.0, "end-1c")

                idx = '1.0'
                while 1:
                    idx = self.text[0].search(self.found, idx, nocase=1, stopindex="end")
                    if not idx: break
                    
                    # if not already found text, set index
                    if scrollto is None:
                        scrollto = i

                    lastidx = f"{idx}+{int(len(self.found))}c"

                    self.text[0].tag_add("select", idx, lastidx)

                    idx = lastidx
        
        # if found any result, scroll to it
        if scrollto is not None:
            fraction = scrollto/len(self.loop)
            self.canvas.yview(tk.MOVETO, fraction)