Python Tkinter中show_info与show_filtered_data函数无法显示最后一列‘Notes’
Tkinter信息录入系统无法显示Excel最后一列"Notes"
我基于Python Tkinter开发的信息录入系统中,show_info和show_filtered_data两个函数在展示Excel数据时,无法显示最后一列‘Notes’,仅能显示8列中的前7列。Excel表格中确实包含完整的8列数据,尝试多种方法甚至求助ChatGPT都未能解决,作为Python新手感到十分困惑。
相关代码如下:
''' This code demonstrates a simple information entry system using Tkinter. The entered information is saved to an Excel file, and the user can also view the information from the Excel file. The code uses the following libraries: - tkinter: For creating the GUI - messagebox: For displaying error or success messages - scrolledtext: For displaying the information in a scrollable text area - openpyxl: For working with Excel files - sys: For exiting the program - tkcalendar: For displaying date entry fields ''' import tkinter as tk from tkinter import messagebox, ttk from tkinter import scrolledtext import openpyxl from openpyxl import load_workbook import sys from tkcalendar import DateEntry def validate_returned(event): input_string = entry_returned.get() if input_string and input_string.upper() not in ['Y', 'N']: entry_returned.delete(0, tk.END) messagebox.showerror("Error", "Please enter 'Y' or 'N'.") def save_to_excel(): # Get the information entered by the user first_name = entry_first_name.get() surname = entry_surname.get() ern = entry_ern.get() first_day_sick = entry_first_day_sick.get() last_day_sick = entry_last_day_sick.get() fit_note_expiry = entry_fit_note_expiry.get() returned = entry_returned.get() notes = entry_notes.get() try: # Load the existing Excel workbook workbook = openpyxl.load_workbook('data.xlsx') sheet = workbook.active except FileNotFoundError: # If the workbook doesn't exist, create a new one workbook = openpyxl.Workbook() sheet = workbook.active # Add headers to the sheet if it's empty if sheet.max_row == 0: sheet.append(["First Name", "Surname", "ERN", "FDS", "LDS", "FitN", "Ret", "Notes"]) # Append the information to the Excel sheet sheet.append([first_name, surname, ern, first_day_sick, last_day_sick, fit_note_expiry, returned, notes]) # Save the Excel file workbook.save('data.xlsx') messagebox.showinfo("Success", "Information saved to Excel file!") # Clear the entry fields entry_first_name.delete(0, tk.END) entry_surname.delete(0, tk.END) entry_ern.delete(0, tk.END) entry_first_day_sick.delete(0, tk.END) entry_last_day_sick.delete(0, tk.END) entry_fit_note_expiry.delete(0, tk.END) entry_returned.delete(0, tk.END) entry_notes.delete(0, tk.END) # Function to show a new window with filtered data def show_filtered_data(): # Load the Excel workbook try: workbook = load_workbook("data.xlsx") # Select the appropriate sheet current_sheet = workbook.active # Define the headers headers = ["First", "Sur", "ERN", "FDS", "LDS", "FitN", "Ret", "Notes"] # Filter rows where "Returned = n" filtered_data = [] for row in current_sheet.iter_rows(values_only=True): if row[6] == "n": filtered_data.append(row) # Create a new window for filtered data filtered_window = tk.Toplevel(window) filtered_window.title("Returned = n") filtered_window.geometry("1500x600") # Create a treeview widget to display the filtered data tree = ttk.Treeview(filtered_window, columns=headers, show="headings") # Set the column headers for header in headers: tree.heading(header, text=header) # Set the style to center-align the data style = ttk.Style() style.configure("Treeview", cellanchor="center") # Set the column alignment to center for col in headers: tree.column(col, anchor="center") # Insert the filtered data into the treeview for row in filtered_data: tree.insert("", tk.END, values=row) tree.pack() except FileNotFoundError: messagebox.showerror("Error", "No data file found!") def show_info(): try: # Load the existing Excel workbook workbook = openpyxl.load_workbook('data.xlsx') # Select the appropriate sheet current_sheet = workbook.active # Get the headers headers = ["First", "Sur", "ERN", "FDS", "LDS", "FitN", "Ret", "Notes"] # Create a new window to display the information info_window = tk.Toplevel() info_window.title("Information Display") # Create a treeview widget tree = ttk.Treeview(info_window, columns=headers, show="headings") # Set the column headers for header in headers: tree.heading(header, text=header) # Set the style to center align the data style = ttk.Style() style.configure("Treeview", cellanchor="center") # Set the column alignment to center for col in headers: tree.column(col, anchor="center") # Get the data from the sheet data = current_sheet.iter_rows(min_row=2, values_only=True) # Insert the data into the treeview for row in data: tree.insert("", tk.END, values=row[:len(headers)]) # Calculate the total width required by all columns total_width = sum(tree.column(col, option="width") for col in headers) # Set the width of the information window to accommodate all columns info_window.geometry(f"{total_width+30}x600") # Create a horizontal scrollbar scrollbar = ttk.Scrollbar(info_window, orient="horizontal", command=tree.xview) # Configure the scrollbar to scroll horizontally with the treeview tree.configure(xscrollcommand=scrollbar.set) # Pack the treeview and scrollbar tree.pack(side="left", fill="both", expand=True) scrollbar.pack(fill="x") except FileNotFoundError: messagebox.showerror("Error", "No data file found!") def close_program(): sys.exit() # Create the main application window window = tk.Tk() window.title("Information Entry") window.geometry("400x600") # Create labels and entry fields label_first_name = tk.Label(window, text="First Name:") label_first_name.pack() entry_first_name = tk.Entry(window) entry_first_name.pack() label_surname = tk.Label(window, text="Surname:") label_surname.pack() entry_surname = tk.Entry(window) entry_surname.pack() label_ern = tk.Label(window, text="ERN:") label_ern.pack() entry_ern = tk.Entry(window) entry_ern.pack() label_first_day_sick = tk.Label(window, text="First Day Sick:") label_first_day_sick.pack() entry_first_day_sick = DateEntry(window) #entry_first_day_sick = tk.Entry(window) entry_first_day_sick.pack() label_last_day_sick = tk.Label(window, text="Last Day Sick:") label_last_day_sick.pack() entry_last_day_sick = DateEntry(window) #entry_last_day_sick = tk.Entry(window) entry_last_day_sick.pack() label_fit_note_expiry = tk.Label(window, text="Fit Note Expiry:") label_fit_note_expiry.pack() entry_fit_note_expiry = DateEntry(window) #entry_fit_note_expiry = tk.Entry(window) entry_fit_note_expiry.pack() label_returned = tk.Label(window, text="Returned Y/N:") label_returned.pack() entry_returned = tk.Entry(window) entry_returned.pack() entry_returned.bind("<KeyRelease>", validate_returned) label_notes = tk.Label(window, text="Notes:") label_notes.pack() entry_notes = tk.Entry(window) entry_notes.pack() # Create a button to save the information to Excel button_save = tk.Button(window, text="Save to Excel", command=save_to_excel) button_save.pack() # Create a button to display the information button_show = tk.Button(window, text="Show Info", command=show_info) button_show.pack() button_close = tk.Button(window, text="Close", command=close_program) button_close.pack() button_filter = tk.Button(window, text="Show Filtered Data", command=show_filtered_data) button_filter.pack() # Start the GUI event loop window.mainloop()
问题原因及修复方案
核心问题
两个函数中,Treeview控件的列宽度未明确设置,且show_filtered_data缺少水平滚动条,导致窗口宽度不足时最后一列"Notes"被挤压隐藏。show_info中的row[:len(headers)]切片是多余操作,但并非直接原因。
具体修复步骤
1. 修复show_info函数
- 移除多余的切片操作,直接传入完整行数据
- 为每列设置固定宽度,确保列能正常显示
- 调整窗口宽度计算逻辑,基于设置的列宽计算
修改后的show_info关键代码段:
# Insert the data into the treeview for row in data: tree.insert("", tk.END, values=row) # 移除多余切片 # 为每列设置固定宽度,保证显示空间 for col in headers: tree.column(col, anchor="center", width=120) # Calculate the total width required by all columns total_width = sum(tree.column(col, option="width") for col in headers) # Set the width of the information window to accommodate all columns info_window.geometry(f"{total_width+30}x600")
2. 修复show_filtered_data函数
- 为每列设置固定宽度
- 添加水平滚动条,支持横向滚动查看所有列
- 调整控件布局,让Treeview和滚动条配合工作
修改后的show_filtered_data关键代码段:
# Set the column alignment to center and add fixed width for col in headers: tree.column(col, anchor="center", width=120) # Insert the filtered data into the treeview for row in filtered_data: tree.insert("", tk.END, values=row) # 添加水平滚动条 scrollbar = ttk.Scrollbar(filtered_window, orient="horizontal", command=tree.xview) tree.configure(xscrollcommand=scrollbar.set) # 调整布局,让滚动条正常工作 tree.pack(side="left", fill="both", expand=True) scrollbar.pack(fill="x")
验证说明
修复后,两个函数的Treeview都会为每列分配足够显示空间,加上水平滚动条的支持,即使窗口宽度临时不足,也能通过滚动查看完整的8列数据,包括"Notes"列。
内容的提问来源于stack exchange,提问作者KCranfield
相关产品推荐
相关产品推荐

