同一Tkinter类内实现多按钮对应CSV数据展示方案问询
Refactoring to Handle Multiple Grade Data in a Single Class
I get what you're aiming for—no need to create a separate frame class for every grade button. Let's adjust your page_two class to handle all the CSV loading and table display directly. Here's the revised code:
import tkinter as tk from tkinter import ttk, messagebox from csv import DictReader # Assume LARGE_FONT and related controller classes (like start_page) are defined elsewhere LARGE_FONT = ("Arial", 12) class page_two(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.config(background='#FAEBEF') self.controller = controller # Store controller reference for back button # Frame to hold all grade buttons button_frame = tk.LabelFrame(self, borderwidth=0, background='#FAEBEF') button_frame.pack(padx=(0,0), pady=(10, 20)) # Frame dedicated to displaying the student data table self.table_container = tk.Frame(self, background='#FAEBEF') self.table_container.pack(fill=tk.BOTH, expand=True, padx=20, pady=10) # Load button images as instance variables (no more messy globals!) self.second_year_icon = tk.PhotoImage(file=r"D:\Academy Management Application\Icons\2nd_year_icon.png") self.first_year_icon = tk.PhotoImage(file=r"D:\Academy Management Application\Icons\1st_year_icon.png") self.tenth_class_icon = tk.PhotoImage(file=r"D:\Academy Management Application\Icons\10th_class_icon.png") self.ninth_class_icon = tk.PhotoImage(file=r"D:\Academy Management Application\Icons\9th_class_icon.png") self.eight_class_icon = tk.PhotoImage(file=r"D:\Academy Management Application\Icons\8th_class_icon.png") self.courses_icon = tk.PhotoImage(file=r"D:\Academy Management Application\Icons\courses_icon.png") self.back_icon = tk.PhotoImage(file=r"D:\Academy Management Application\Icons\back_icon.png") # Grade buttons - each triggers the generic data loader with its CSV path tk.Button(button_frame, font=LARGE_FONT, image=self.second_year_icon, border=0, command=lambda: self.load_student_data("second_year_data.csv")).grid( row=0, column=0, padx=(10,10), pady=(10,0), sticky=tk.E) tk.Button(button_frame, font=LARGE_FONT, image=self.first_year_icon, border=0, command=lambda: self.load_student_data("first_year_data.csv")).grid( row=0, column=1, padx=(10,10), pady=(10,0), sticky=tk.E) tk.Button(button_frame, font=LARGE_FONT, image=self.tenth_class_icon, border=0, command=lambda: self.load_student_data("tenth_class_data.csv")).grid( row=1, column=0, padx=(10,10), pady=(10,0), sticky=tk.E) tk.Button(button_frame, font=LARGE_FONT, image=self.ninth_class_icon, border=0, command=lambda: self.load_student_data("ninth_class_data.csv")).grid( row=1, column=1, padx=(10,10), pady=(10,0), sticky=tk.E) tk.Button(button_frame, font=LARGE_FONT, image=self.eight_class_icon, border=0, command=lambda: self.load_student_data("eight_class_data.csv")).grid( row=2, column=0, padx=(10,10), pady=(10,0)) tk.Button(button_frame, font=LARGE_FONT, image=self.courses_icon, border=0, command=lambda: self.load_student_data("courses_data.csv")).grid( row=2, column=1, padx=(10,10), pady=(10,0)) # Back navigation button tk.Button(button_frame, font=LARGE_FONT, image=self.back_icon, border=0, command=lambda: controller.show_frame(start_page)).grid( row=3, pady=(10,0), columnspan=2) def load_student_data(self, csv_file_path): # Clear any existing table widgets to avoid overlapping for widget in self.table_container.winfo_children(): widget.destroy() # Set up scrollbars and Treeview for data display scrollbarx = ttk.Scrollbar(self.table_container, orient='horizontal') scrollbary = ttk.Scrollbar(self.table_container, orient='vertical') tree = ttk.Treeview( self.table_container, columns=("Registration No", "Student Name", "Father Name"), height=15, selectmode="extended", yscrollcommand=scrollbary.set, xscrollcommand=scrollbarx.set ) # Configure scrollbar placement scrollbary.config(command=tree.yview) scrollbary.pack(side=tk.RIGHT, fill=tk.Y) scrollbarx.config(command=tree.xview) scrollbarx.pack(side=tk.BOTTOM, fill=tk.X) # Configure Treeview headings and columns tree.heading('#0', text="", anchor='w') # Hide the default empty first column tree.heading('Registration No', text="Registration No", anchor='w') tree.heading('Student Name', text="Student Name", anchor='w') tree.heading('Father Name', text="Father Name", anchor='w') tree.column('#0', stretch='NO', minwidth=0, width=0) tree.column('Registration No', stretch='NO', minwidth=0, width=150) tree.column('Student Name', stretch='NO', minwidth=0, width=200) tree.column('Father Name', stretch='NO', minwidth=0, width=200) tree.pack(fill=tk.BOTH, expand=True) # Load and insert data from CSV, with error handling try: with open(csv_file_path, newline='', encoding='utf-8') as f: reader = DictReader(f, delimiter=',') for row in reader: tree.insert( "", tk.END, values=(row['Registration No'], row['Student Name'], row['Father Name']) ) except FileNotFoundError: messagebox.showerror("Error", f"Could not find the file: {csv_file_path}") except KeyError as e: messagebox.showerror("Error", f"Missing required column in CSV: {e}") # Example controller and start page (for context) class AppController(tk.Tk): def __init__(self, *args, **kwargs): tk.Tk.__init__(self, *args, **kwargs) container = tk.Frame(self) container.pack(fill=tk.BOTH, expand=True) self.frames = {} for F in (start_page, page_two): frame = F(container, self) self.frames[F] = frame frame.grid(row=0, column=0, sticky="nsew") self.show_frame(start_page) def show_frame(self, cont): frame = self.frames[cont] frame.tkraise() class start_page(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) tk.Button(self, text="Go to Grade Selection", command=lambda: controller.show_frame(page_two)).pack(pady=50) if __name__ == "__main__": app = AppController() app.mainloop()
Key Improvements & Explanations:
- Single-Class Management: All grade button logic and data display lives inside
page_two—no more separate frame classes for each grade. - Generic Data Loader: The
load_student_datamethod is reusable for any CSV file. It handles clearing old widgets, creating a fresh table, loading data, and even basic error handling for missing files or columns. - Instance Variables: Swapped global image variables for
self.*_iconto keep the code clean and avoid scope-related bugs. - Dynamic Refresh: Every button click destroys the old table and creates a new one, ensuring only the selected grade's data is displayed.
- Error Handling: Added user-friendly error messages to help troubleshoot missing files or incorrectly formatted CSVs.
Just remember to update the CSV file paths in each button's command to match your actual file locations!
内容的提问来源于stack exchange,提问作者Osama Shakeel
相关产品推荐
相关产品推荐

