tkinter中树视图的功能搜索栏



我正在编写一个程序,用给定.csv文件中的数据创建树视图。我想得到一个正常工作的搜索栏,这样它只显示包含搜索栏中所写内容的结果,我遇到了麻烦。如有任何帮助,我们将不胜感激。

from tkinter import *
from tkinter import ttk
import pandas as pd
import tkinter as tk
def filterTreeView(*args):
ItemsOnTreeView = myTree.get_children()
search = search_ent_var.get().capitalize()
for eachItem in ItemsOnTreeView:
if search in myTree.item(eachItem)['values'][2]:
search_var = myTree.item(eachItem)['values']
myTree.delete(eachItem)
myTree.insert("", 0, value=search_var)
root = Tk()
root.title("NSW Traffic Penalty Data")
topFrame = Frame(root, bg="white")
topFrame.place(x=5, y=5, width=200, height=80)
treeFrame = Frame(root, bg="white")
treeFrame.place(x=5, y=100, width=1500, height=800)
lb1 = Label(topFrame, text="Search by", fg="black", bg="white")
lb1.grid(row=0, column=0)
search_ent_var = StringVar()
myentry = Entry(topFrame, textvariable=search_ent_var)
myentry.grid(row=0, column=1)
search_ent_var.trace("w", filterTreeView())
column = ['Financial Year', 'Month', 'Offence Code', 'Offence Description', 'Legislation', 'Section Clause',
'Penalty Amount', 'Camera Offence', 'Camera Type', 'Camera Location', 'Camera Location Details', 'School Zone',
'Speed Range', 'Speed Offence', 'Point to Point Offence', 'Red Light Camera Offence', 'Speed Camera Offence',
'Seatbelt Offence', 'Mobile Phone Offence', 'Parking Offence', 'Criminal Infringement Notice Scheme Offence',
'Food Safety Offence', 'Non-Motor Vehicle Offence', 'Number of Penalty Notices', 'Total Value of Penalty Notices']
data = pd.read_csv("penalty_data_set_2.csv")
data_rows = data.to_numpy().tolist()
myTree = ttk.Treeview(treeFrame, height=100, column=column)
myTree.place(relheight=1, relwidth=1)
myTree['show']='headings'
treescrolly = tk.Scrollbar(treeFrame, orient="vertical", command=myTree.yview)
treescrollx = tk.Scrollbar(treeFrame, orient="horizontal", command=myTree.xview)
myTree.configure(xscrollcommand=treescrollx.set, yscrollcommand=treescrolly.set)
treescrollx.pack(side="bottom", fill="x")
treescrolly.pack(side="right", fill="y")
for each in column:
myTree.column(each, width=80)
myTree.heading(each, text=each.capitalize())
for each in data_rows:
myTree.insert("", "end", values = each)
root.mainloop()

首先需要将函数引用传递给.trace(...),因此需要将search_ent_var.trace("w", filterTreeView())更改为search_ent_var.trace("w", filterTreeView)

其次,您需要通过data_rows,而不是filterTreeView()函数中的myTree行:

def filterTreeView(*args):
search = search_ent_var.get().capitalize()
# first clear the treeview
myTree.delete(*myTree.get_children())
# then insert matched items into treeview
for item in data_rows:
if search in item[2]:
myTree.insert("", "end", values=item)

你很幸运,我自己也玩过python中的一些UI东西。我想在树视图之外工作,而不是在内存中维护单独的数据库。也许,如果列表变大,这会减少UI滞后。我使用了上面评论中的链接帖子作为跟踪分离项目的指南。

以下是一个完整的工作示例。。。

import tkinter
import tkinter.font as tkFont
from tkinter import TclError, ttk
data_header = (
'First', 'Last', 'Game', 'Food',
)
data_rows = [
('Mickey',      'Mouse',    'Hide-and-Squeak',  'Tacos'),
('Minnie',      'Mouse',    'Hide-and-Squeak',  'Burgers'),
('Mortimer',    'Mouse',    'Hide-and-Squeak',  'Pizza'),
('Donald',      'Duck',     'Checkers',         'Pizza'),
('Daisy',       'Duck',     'Checkers',         'Pizza'),
('Ludwig',      'Von Drake','Poker',            'Sushi'),
('Scrooge',     'McDuck',   'Solitare',         'McNuggets'),
('Clarabelle',  'Cow',      'Poker',            'Tacos'),
]

def tree_sortby(tree, column, descending = False):
"""sort tree contents when a column header is clicked on"""
data = [(tree.set(child, column), child) for child in tree.get_children('')]
# different types could require a sorting function
data.sort(reverse = descending)
for ix, item in enumerate(data):
tree.move(item[1], '', ix)
# switch the heading so it will sort in the opposite direction
tree.heading(column, command =
lambda col = column: tree_sortby(tree, col, bool(not descending)))

class App(tkinter.Tk):
_detached = set()
def tree_reset(self):
children = list(self._detached) + list(self.tree.get_children())
self._detached = set()
self.filter_re.set('')
# enumerate so that order is preserved?
for ix, item_id in enumerate(children):
self.tree.reattach(item_id, '', ix)
def tree_filter(self, *args):
children = list(self._detached) + list(self.tree.get_children())
self._detached = set()
query = self.filter_re.get()
i_r = -1
for _, item_id in enumerate(children):
text = ' '.join(self.tree.item(item_id, 'values'))
if query in text:
i_r += 1
self.tree.reattach(item_id, '', i_r)
else:
self._detached.add(item_id)
self.tree.detach(item_id)

def __init__(self):
super().__init__()
self.title('Tree Filter Test')
self.geometry('200x200')
self.resizable(True, True)
self.minsize(200, 200)
try:
# windows only (remove the minimize/maximize button)
self.attributes('-toolwindow', True)
except TclError:
print('Not supported on your platform')
# define layout
self.columnconfigure(0, weight=0)
self.columnconfigure(1, weight=1)
self.columnconfigure(2, weight=0)
self.columnconfigure(3, weight=0)
self.rowconfigure(0, weight=0)
self.rowconfigure(1, weight=1)
self.rowconfigure(2, weight=0)
self.filter_re = tkinter.StringVar()
ttk.Label(self, text = 'Filter: ').grid(column = 0, row = 0, sticky = tkinter.W)
searchfield = ttk.Entry(self, textvariable = self.filter_re).grid(
column = 1, row = 0, sticky='nsew')
ttk.Button(self, text = 'Reset', command = self.tree_reset).grid(
column = 2, row = 0, columnspan=2, sticky = tkinter.E)
# TODO, why can't we just repond to changes is the edit field?
self.filter_re.trace("w", self.tree_filter)
self.tree = ttk.Treeview(self, column = data_header)
scroll_x = ttk.Scrollbar(self, command = self.tree.xview, orient = tkinter.HORIZONTAL)
scroll_x.grid(column = 0, row = 2, columnspan = 3, sticky = 'we')
scroll_y = ttk.Scrollbar(self, command = self.tree.yview, orient = tkinter.VERTICAL)
scroll_y.grid(column = 3, row = 1, sticky='ns')
self.tree.configure(xscrollcommand = scroll_x.set, yscrollcommand = scroll_y.set)
self.tree.column('#0', width = 1)
for label in self.tree["column"]:
self.tree.heading(label, text = label,
command = lambda column = label: tree_sortby(self.tree, column))
self.tree.column(label, width = tkFont.Font().measure(label.title()))
for row in data_rows:
self.tree.insert('', 'end', values = row)
# TODO, expand each column to fit data
self.tree.grid(column=0, row=1, columnspan=3, sticky='nsew')

if __name__ == "__main__":
app = App()
app.mainloop()

最新更新