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)
这是我的应用程序的一个小副本,我在其中使用 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)