Tkinter Treeview技术需求:删除非搜索结果项,仅保留已高亮的搜索条目
Got it, let's work through this problem together. You want to strip your Tkinter Treeview down to only the highlighted search results, removing all other entries. Here's how to make that happen, plus fixes for a couple of small issues in your existing code:
First, let's address a critical variable scope issue in your code: right now my_tree is a local variable inside excel_list(), so search_records() can't access it at all. We'll fix that first, then implement the logic to retain only highlighted entries.
The core steps we'll follow:
- Make the Treeview accessible to both functions
- Collect the data of all selected/highlighted records
- Delete every entry from the Treeview
- Re-insert only the collected selected data back into the Treeview
Modified Working Code
import tkinter as tk from tkinter import ttk, Frame, Toplevel, Entry, Button import pandas as pd # Declare Treeview as a global variable to share between functions my_tree = None def excel_list(): global my_tree # Use global keyword to modify the global variable file = 'ddata.xlsx' listy = Toplevel() listy.title("EXCEL JOB DATA") listy.geometry("1000x500") df = pd.read_excel(file) # Create Treeview frame my_frame = Frame(listy) my_frame.pack(pady=20) tree_scroll = Scrollbar(my_frame) tree_scroll.pack(side=RIGHT, fill=Y) my_tree = ttk.Treeview(my_frame, yscrollcommand=tree_scroll.set) my_tree['column'] = list(df.columns) my_tree['show'] = 'headings' # Set up column headings for column in my_tree['column']: my_tree.heading(column, text=column) # Insert all rows from Excel df_rows = df.to_numpy().tolist() for row in df_rows: my_tree.insert('', 'end', values=row) my_tree.pack() tree_scroll.config(command=my_tree.yview) def search_records(): global my_tree # Access the global Treeview variable if not my_tree: print("Load Excel data first!") return lookup_record = search_entry.get() selected_data = [] print(lookup_record) # First, collect data of all matching/highlighted records for record in my_tree.get_children(): row_values = my_tree.item(record)['values'] if lookup_record in row_values: selected_data.append(row_values) # Delete all entries from the Treeview for record in my_tree.get_children(): my_tree.delete(record) # Re-insert only the selected search results for row in selected_data: my_tree.insert('', 'end', values=row) # Example main window setup (adjust to match your existing UI) root = tk.Tk() root.title("Main Window") search_entry = Entry(root, width=30) search_entry.pack(pady=10) search_btn = Button(root, text="Search & Keep Results", command=search_records) search_btn.pack(pady=5) list_btn = Button(root, text="Load Excel Data", command=excel_list) list_btn.pack(pady=5) root.mainloop()
Key Details Explained
- Global Variable Fix: By declaring
my_treeas a global variable, bothexcel_list()(which creates the Treeview) andsearch_records()(which modifies it) can interact with the same widget. - Data Preservation: We save the values of matching records before deleting anything — this ensures we don't lose the data we want to keep.
- Clean Slate + Re-insert: After clearing the entire Treeview, we add back only the saved search results, leaving you with exactly the highlighted entries you wanted.
Alternative: Class-Based Approach (Better for Scalability)
If you're building a larger app, using a class to encapsulate your Treeview and operations avoids messy global variables. Here's a quick snippet:
import tkinter as tk from tkinter import ttk, Frame, Toplevel, Entry, Button import pandas as pd class ExcelTreeApp: def __init__(self, root): self.root = root self.root.title("Main Window") # UI Elements self.search_entry = Entry(root, width=30) self.search_entry.pack(pady=10) self.search_btn = Button(root, text="Search & Keep Results", command=self.search_records) self.search_btn.pack(pady=5) self.load_btn = Button(root, text="Load Excel Data", command=self.load_excel_data) self.load_btn.pack(pady=5) self.treeview = None def load_excel_data(self): file = 'ddata.xlsx' window = Toplevel(self.root) window.title("EXCEL JOB DATA") window.geometry("1000x500") df = pd.read_excel(file) frame = Frame(window) frame.pack(pady=20) scrollbar = Scrollbar(frame) scrollbar.pack(side=RIGHT, fill=Y) self.treeview = ttk.Treeview(frame, yscrollcommand=scrollbar.set) self.treeview['column'] = list(df.columns) self.treeview['show'] = 'headings' for col in self.treeview['column']: self.treeview.heading(col, text=col) for row in df.to_numpy().tolist(): self.treeview.insert('', 'end', values=row) self.treeview.pack() scrollbar.config(command=self.treeview.yview) def search_records(self): if not self.treeview: print("Load Excel data first!") return lookup = self.search_entry.get() selected_rows = [] for item in self.treeview.get_children(): values = self.treeview.item(item)['values'] if lookup in values: selected_rows.append(values) # Clear and re-populate for item in self.treeview.get_children(): self.treeview.delete(item) for row in selected_rows: self.treeview.insert('', 'end', values=row) if __name__ == "__main__": root = tk.Tk() app = ExcelTreeApp(root) root.mainloop()
This class keeps all related code together, making it easier to maintain and extend as your app grows.
内容的提问来源于stack exchange,提问作者wayne

