在树视图中搜索 highlight/select 包含所搜索项目的行
searching in treeview and highlight/select the row that contains the item that is searched
我正在使用 tkinter 和 treeview 为带有患者姓名和就诊日期的患者列表制作一个简单的 GUI,我有一个条目,用户应该在其中输入患者的姓名,我的想法是如果patient 位于列表中,包含要突出显示(选择)的患者姓名的行(或多行)。或者另一个选项可以在所有患者的列表框中,只显示我们搜索的患者姓名的条目。
我以前没有使用过 treeview,也找不到太多关于它的功能和示例的数据,所以我在 selection/highlight 部分苦苦挣扎,此时任何想法都会有所帮助....
到目前为止我的代码是:
import tkinter
from tkinter import ttk
class MainPage:
def __init__(self,master):
self.master = master
self.frame = tkinter.Frame(self.master)
self.master.columnconfigure(0, weight=1)
self.master.columnconfigure(1, weight=3)
self.master.columnconfigure(2, weight=1)
self.master.columnconfigure(3, weight=1)
self.master.columnconfigure(4, weight=1)
self.searchfield = tkinter.Frame(self.master)
self.searchfield.grid(row=1, column=0, columnspan=4)
self.search_var = tkinter.StringVar()
self.search_var.trace("w", lambda name, index, mode: self.selected)
self.entry = tkinter.Entry(self.searchfield,
textvariable=self.search_var, width=45)
self.entry.grid(row=0, column=0, padx=10, pady=3)
self.searchbtn = tkinter.Button(self.searchfield, text='Search',
command=self.selected)
self.searchbtn.grid(row=0, column=1)
self.treeFrame = tkinter.Listbox(self.searchfield, width=45, height=45)
self.treeFrame.grid(row=1, column=0, padx=10, pady=3)
self.tree = ttk.Treeview( self.treeFrame, columns=('Name', 'Date'))
self.tree.heading('#0', text='ID')
self.tree.heading('#1', text='Name')
self.tree.heading('#2', text='Date')
self.tree.column('#1', stretch=tkinter.YES)
self.tree.column('#2', stretch=tkinter.YES)
self.tree.column('#0', stretch=tkinter.YES)
self.tree.grid(row=4, columnspan=4, sticky='nsew')
self.treeview = self.tree
self.i = 1
self.patient_list = [{"Name": "Jane", "Date": "05.09.2017"},
{"Name": "David", "Date": "04.09.2017"},
{"Name": "Patrick", "Date": "03.09.2017"}]
for p in self.patient_list:
self.tree.insert('', 'end', text="ID_"+str(self.i), values=
(p["Name"], p["Date"]))
self.i = self.i + 1
self.search_item = self.entry.get()
for p in self.patient_list:
if p["Name"] == self.search_item:
self.selected(self.search_item)
def selected(self):
currentItem = self.tree.focus()
print(self.tree.item(currentItem)['values'])
root=tkinter.Tk()
d=MainPage(root)
root.mainloop()
提前致谢!
请看下面我解释的片段:
from tkinter import *
from tkinter import ttk
class App:
def __init__(self, root):
self.root = root
self.tree = ttk.Treeview(self.root) #create tree
self.sv = StringVar() #create stringvar for entry widget
self.sv.trace("w", self.command) #callback if stringvar is updated
self.entry = Entry(self.root, textvariable=self.sv) #create entry
self.names = ["Jane", "Janet", "James", "Jamie"] #these are just test inputs for the tree
self.ids = [] #creates a list to store the ids of each entry in the tree
for i in range(len(self.names)):
#creates an entry in the tree for each element of the list
#then stores the id of the tree in the self.ids list
self.ids.append(self.tree.insert("", "end", text=self.names[i]))
self.tree.pack()
self.entry.pack()
def command(self, *args):
self.selections = [] #list of ids of matching tree entries
for i in range(len(self.names)):
#the below if check checks if the value of the entry matches the first characters of each element
#in the names list up to the length of the value of the entry widget
if self.entry.get() != "" and self.entry.get() == self.names[i][:len(self.entry.get())]:
self.selections.append(self.ids[i]) #if it matches it appends the id to the selections list
self.tree.selection_set(self.selections) #we then select every id in the list
root = Tk()
App(root)
root.mainloop()
因此,每次 entry
小部件更新时,我们循环遍历名称列表并检查 entry
小部件的值是否与 [=13= 的值匹配] 在 names
list
中直到 entry
小部件的值的长度(EG,如果我们输入一个五个字符长的字符串,那么我们检查元素的前五个字符).
如果它们匹配,那么我们将树条目的 id
附加到 list
。
检查完所有名称后,我们将匹配 id
的 list
传递给 self.tree.selection_set()
,然后突出显示所有匹配的树条目。
某种搜索已经直接在框中实现,因此不需要另一个!
您需要做的就是为您的患者提供合适的标签。之后,您可以通过这些标签进行搜索(是的,您可以向指定患者提供多个标签)并控制 appearance/highlighting 患者(树视图行)。
来玩玩吧:
class MainPage:
def __init__(self,master):
# ...
for p in self.patient_list:
# Note tags argument, right now we use names of patients
self.tree.insert('', 'end', text="ID_" + str(self.i), values=
(p["Name"], p["Date"]), tags=p["Name"])
# ...
# ...
def selected(self):
# setting selection by iids with tag (name of a patient or whatever)
self.tree.selection_set(self.tree.tag_has(self.search_var.get()))
# ...
现在这只是强调一个病人...
...但是您可以使用一对 .detach()
和 .move()
轻松修改它以对整个树视图进行排序。
此外,您可以使用几行代码实现部分搜索:
class MainPage:
# ...
def selected(self):
search_for = self.search_var.get()
iid_to_select = ()
# if there's any sense in search
if search_for != '':
# get all tags from tkinter
all_tags = self.master.tk.call(str(self.tree), "tag", "names")
# sort tags by search query
tags_to_select = tuple(filter(lambda tag: search_for.lower() in tag.lower(), all_tags))
# gather iids by tags to select
for sorted_tag in tags_to_select:
iid_to_select += self.tree.tag_has(sorted_tag)
# setting selection by iids
self.tree.selection_set(iid_to_select)
# ...
总而言之,没有必要重新发明轮子,但如果您的树视图可由用户更改 - 请记住,这些标签必须与可变内容同步。
可以找到更多关于 treeview 的信息 here。
我正在使用 tkinter 和 treeview 为带有患者姓名和就诊日期的患者列表制作一个简单的 GUI,我有一个条目,用户应该在其中输入患者的姓名,我的想法是如果patient 位于列表中,包含要突出显示(选择)的患者姓名的行(或多行)。或者另一个选项可以在所有患者的列表框中,只显示我们搜索的患者姓名的条目。
我以前没有使用过 treeview,也找不到太多关于它的功能和示例的数据,所以我在 selection/highlight 部分苦苦挣扎,此时任何想法都会有所帮助....
到目前为止我的代码是:
import tkinter
from tkinter import ttk
class MainPage:
def __init__(self,master):
self.master = master
self.frame = tkinter.Frame(self.master)
self.master.columnconfigure(0, weight=1)
self.master.columnconfigure(1, weight=3)
self.master.columnconfigure(2, weight=1)
self.master.columnconfigure(3, weight=1)
self.master.columnconfigure(4, weight=1)
self.searchfield = tkinter.Frame(self.master)
self.searchfield.grid(row=1, column=0, columnspan=4)
self.search_var = tkinter.StringVar()
self.search_var.trace("w", lambda name, index, mode: self.selected)
self.entry = tkinter.Entry(self.searchfield,
textvariable=self.search_var, width=45)
self.entry.grid(row=0, column=0, padx=10, pady=3)
self.searchbtn = tkinter.Button(self.searchfield, text='Search',
command=self.selected)
self.searchbtn.grid(row=0, column=1)
self.treeFrame = tkinter.Listbox(self.searchfield, width=45, height=45)
self.treeFrame.grid(row=1, column=0, padx=10, pady=3)
self.tree = ttk.Treeview( self.treeFrame, columns=('Name', 'Date'))
self.tree.heading('#0', text='ID')
self.tree.heading('#1', text='Name')
self.tree.heading('#2', text='Date')
self.tree.column('#1', stretch=tkinter.YES)
self.tree.column('#2', stretch=tkinter.YES)
self.tree.column('#0', stretch=tkinter.YES)
self.tree.grid(row=4, columnspan=4, sticky='nsew')
self.treeview = self.tree
self.i = 1
self.patient_list = [{"Name": "Jane", "Date": "05.09.2017"},
{"Name": "David", "Date": "04.09.2017"},
{"Name": "Patrick", "Date": "03.09.2017"}]
for p in self.patient_list:
self.tree.insert('', 'end', text="ID_"+str(self.i), values=
(p["Name"], p["Date"]))
self.i = self.i + 1
self.search_item = self.entry.get()
for p in self.patient_list:
if p["Name"] == self.search_item:
self.selected(self.search_item)
def selected(self):
currentItem = self.tree.focus()
print(self.tree.item(currentItem)['values'])
root=tkinter.Tk()
d=MainPage(root)
root.mainloop()
提前致谢!
请看下面我解释的片段:
from tkinter import *
from tkinter import ttk
class App:
def __init__(self, root):
self.root = root
self.tree = ttk.Treeview(self.root) #create tree
self.sv = StringVar() #create stringvar for entry widget
self.sv.trace("w", self.command) #callback if stringvar is updated
self.entry = Entry(self.root, textvariable=self.sv) #create entry
self.names = ["Jane", "Janet", "James", "Jamie"] #these are just test inputs for the tree
self.ids = [] #creates a list to store the ids of each entry in the tree
for i in range(len(self.names)):
#creates an entry in the tree for each element of the list
#then stores the id of the tree in the self.ids list
self.ids.append(self.tree.insert("", "end", text=self.names[i]))
self.tree.pack()
self.entry.pack()
def command(self, *args):
self.selections = [] #list of ids of matching tree entries
for i in range(len(self.names)):
#the below if check checks if the value of the entry matches the first characters of each element
#in the names list up to the length of the value of the entry widget
if self.entry.get() != "" and self.entry.get() == self.names[i][:len(self.entry.get())]:
self.selections.append(self.ids[i]) #if it matches it appends the id to the selections list
self.tree.selection_set(self.selections) #we then select every id in the list
root = Tk()
App(root)
root.mainloop()
因此,每次 entry
小部件更新时,我们循环遍历名称列表并检查 entry
小部件的值是否与 [=13= 的值匹配] 在 names
list
中直到 entry
小部件的值的长度(EG,如果我们输入一个五个字符长的字符串,那么我们检查元素的前五个字符).
如果它们匹配,那么我们将树条目的 id
附加到 list
。
检查完所有名称后,我们将匹配 id
的 list
传递给 self.tree.selection_set()
,然后突出显示所有匹配的树条目。
某种搜索已经直接在框中实现,因此不需要另一个!
您需要做的就是为您的患者提供合适的标签。之后,您可以通过这些标签进行搜索(是的,您可以向指定患者提供多个标签)并控制 appearance/highlighting 患者(树视图行)。
来玩玩吧:
class MainPage:
def __init__(self,master):
# ...
for p in self.patient_list:
# Note tags argument, right now we use names of patients
self.tree.insert('', 'end', text="ID_" + str(self.i), values=
(p["Name"], p["Date"]), tags=p["Name"])
# ...
# ...
def selected(self):
# setting selection by iids with tag (name of a patient or whatever)
self.tree.selection_set(self.tree.tag_has(self.search_var.get()))
# ...
现在这只是强调一个病人...
.detach()
和 .move()
轻松修改它以对整个树视图进行排序。
此外,您可以使用几行代码实现部分搜索:
class MainPage:
# ...
def selected(self):
search_for = self.search_var.get()
iid_to_select = ()
# if there's any sense in search
if search_for != '':
# get all tags from tkinter
all_tags = self.master.tk.call(str(self.tree), "tag", "names")
# sort tags by search query
tags_to_select = tuple(filter(lambda tag: search_for.lower() in tag.lower(), all_tags))
# gather iids by tags to select
for sorted_tag in tags_to_select:
iid_to_select += self.tree.tag_has(sorted_tag)
# setting selection by iids
self.tree.selection_set(iid_to_select)
# ...
总而言之,没有必要重新发明轮子,但如果您的树视图可由用户更改 - 请记住,这些标签必须与可变内容同步。
可以找到更多关于 treeview 的信息 here。