Tkinter Treeview设置列宽为0后残留黄色像素问题求助
问题:Treeview隐藏列后残留黄色像素
我通过点击右侧按钮切换视图,仅显示特定列,实现逻辑是将不需要的列宽度设为0来隐藏。虽然列已隐藏,但原位置残留黄色像素,视觉效果不佳,请问如何去除这些黄色像素?
代码说明
数据表格窗口: 用户点击按钮(如"显示数据表格")时打开数据表格窗口。 使用pd.read_excel加载Excel文件到Pandas DataFrame(df)中。 窗口配置: 窗口配置为支持交互式显示带样式的DataFrame。 创建ttk.Treeview组件来展示DataFrame的列。 设置列标题和宽度。 添加滚动条用于Treeview导航。 搜索功能: 添加搜索输入框和搜索按钮,用于查找特定数据。 用户按回车键或点击搜索按钮时调用search_data函数。 视图切换按钮: 添加多个按钮(如"每日视图"、"订单视图"、"每周视图")来激活特定视图。 调用对应的函数(show_tagesbasis、show_bestellbasis、show_wochenbasis)隐藏列并更新视图。 重置按钮: 添加"重置"按钮,将视图恢复到初始状态。 调用reset_view函数重新显示所有列并更新视图。 颜色编码(已注释): 原本有单元格颜色编码逻辑,但已被注释掉。
相关代码
# 导入必要的库和模块 import tkinter as tk from tkinter import ttk # 导入主题tk模块 from tkcalendar import DateEntry # 日历功能 from babel import numbers import datetime # 日期转换 import matplotlib matplotlib.use("TkAgg") # 使用Tkinter作为绘图后端 from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg import matplotlib.pyplot as plt # 绘图功能 import numpy as np # 绘图功能 import matplotlib.dates as mdates # 日期转换为星期 import locale # X轴标签设为德语 from PIL import Image, ImageTk # 图片功能 import pandas as pd # 导入pandas读取Excel数据 from tkinter.ttk import Separator import mplcursors # 图表点鼠标悬停 import warnings # 过滤图表鼠标悬停警告:"PolyCollection缺少拾取支持,且Selection.target.index属性已弃用。" import time # 启动屏幕进度条 import threading # 启动屏幕进度条 from functools import partial # 将进度条与DataFrame加载关联 from tkinter import messagebox # 错误提示(如Excel数据为空) import os def on_datenblatt_button_click(): print("函数启动") try: # 加载Excel文件 file_path = 'data/Input.xlsx' df = pd.read_excel(file_path) # 检查窗口是否已打开 if hasattr(on_datenblatt_button_click, 'styled_window') and on_datenblatt_button_click.styled_window.winfo_exists(): # 若已打开则关闭窗口 on_datenblatt_button_click.styled_window.destroy() return # 退出函数避免重复打开 # 数字保留两位小数 df = df.round(2) # 创建新窗口用于交互式显示带样式的DataFrame styled_window = tk.Toplevel(start_window) styled_window.title("数据表格") # 将窗口保存为函数属性以便后续访问 on_datenblatt_button_click.styled_window = styled_window # 窗口尺寸配置(居中显示) window_width = 1000 window_height = 600 styled_window.geometry(f'{window_width}x{window_height}') # screen_width = styled_window.winfo_screenwidth() # screen_height = styled_window.winfo_screenheight() # x_coordinate = int((screen_width - window_width) / 2) # y_coordinate = int((screen_height - window_height) / 2) # styled_window.geometry(f'{window_width}x{window_height}+{x_coordinate}+{y_coordinate}') # 创建带样式的ttk.Treeview组件 style = ttk.Style() style.configure("Treeview", font=('Arial', 12)) tree = ttk.Treeview(styled_window) tree["columns"] = list(df.columns) tree["show"] = "headings" # 不显示左侧空列 # 添加列标题 col_width = 120 # 设置所有列宽度 for col in df.columns: tree.heading(col, text=col) tree.column(col, width=col_width, stretch=tk.NO) # 设置stretch为tk.NO,宽度为col_width # 放置Treeview组件 tree.pack(fill='both', side='left') # 添加滚动条 scrollbar = ttk.Scrollbar(styled_window, orient='vertical', command=tree.yview) scrollbar.pack(side='right', fill='y') tree.configure(yscrollcommand=scrollbar.set) # 创建搜索框架 search_frame = ttk.Frame(styled_window) search_frame.pack(side='top', fill='x') # 搜索输入框 search_entry = ttk.Entry(search_frame) search_entry.grid(row=0, column=0, padx=5, pady=5) # 绑定回车键触发搜索 search_entry.bind('<Return>', lambda event: search_data(tree, df, search_entry.get())) # 搜索按钮 search_button = ttk.Button(search_frame, text="搜索", command=lambda: search_data(tree, df, search_entry.get())) search_button.grid(row=1, column=0, padx=5, pady=5) # 空白框架用于间距 ttk.Frame(search_frame, height=10).grid(row=2, column=0) # 视图切换按钮 tagesbasis_button = ttk.Button(search_frame, text="每日视图", command=lambda: show_tagesbasis(tree, df, styled_window)) tagesbasis_button.grid(row=3, column=0, padx=5, pady=5) bestellbasis_button = ttk.Button(search_frame, text="订单视图", command=lambda: show_bestellbasis(tree, df, styled_window)) bestellbasis_button.grid(row=4, column=0, padx=5, pady=5) wochenbasis_button = ttk.Button(search_frame, text="每周视图", command=lambda: show_wochenbasis(tree, df, styled_window)) wochenbasis_button.grid(row=5, column=0, padx=5, pady=5) # 空白框架用于间距 ttk.Frame(search_frame, height=10).grid(row=6, column=0) reset_button = ttk.Button(search_frame, text="重置", command=lambda: reset_view(tree, df)) reset_button.grid(row=7, column=0, padx=5, pady=5) # # 设置单元格颜色 # for tag in ['green', 'yellow', 'red']: # tree.tag_configure(tag, background='') # 添加数据条目(无颜色) for index, row in df.iterrows(): values = list(row) tree.insert("", tk.END, values=values, iid=index) # 保存最新日期和索引的选中状态 if index == df.index[-1]: styled_window.selected_date = row['Date'] styled_window.selected_index = index # 设置选中最新日期 tree.selection_set(styled_window.selected_index) tree.see(styled_window.selected_index) except Exception as e: print(f"发生错误: {e}") print("函数结束") def search_data(tree, df, search_date): try: # 将日期转为字符串后搜索 matching_rows = df.index[df['Date'].astype(str).str.contains(search_date, case=False, na=False)].tolist() if matching_rows: tree.selection_set(matching_rows[0]) tree.see(matching_rows[0]) except Exception as e: print(f"搜索时发生错误: {e}") # def color_by_deviation(prognose_value, ist_value): # color = 'green' if ist_value == 0 or prognose_value == 0 else ( # 'green' if abs(ist_value - prognose_value) / ist_value <= 0.1 else ( # 'yellow' if abs(ist_value - prognose_value) / ist_value <= 0.3 else 'red' # ) # ) # return color def show_tagesbasis(tree, df, styled_window): reset_view(tree, df) hide_column(tree, df, styled_window, '(Actual) Order', 'Forecast Order', '(Actual) Week', 'Forecast Week') def show_bestellbasis(tree, df, styled_window): reset_view(tree, df) hide_column(tree, df, styled_window, '(Actual) Sales', 'Forecast Sales', '(Actual) Week', 'Forecast Week') def show_wochenbasis(tree, df, styled_window): reset_view(tree, df) hide_column(tree, df, styled_window, '(Actual) Sales', 'Forecast Sales', '(Actual) Order', 'Forecast Order') def reset_view(tree, df): show_all_columns(tree, df) # reset_colors(tree) update_entries(tree, df) def hide_column(tree, df, styled_window, *columns_to_hide): for col in columns_to_hide: # 隐藏列 tree.column(col, width=0, stretch=tk.NO) # 更新Treeview组件 styled_window.update_idletasks() def update_entries(tree, df): for index, row in df.iterrows(): values = list(row) tree.item(index, values=values) def show_all_columns(tree, df): for col in df.columns: tree.column(col, width=120, stretch=tk.NO)
解决方案
1. 彻底移除列而非仅设置宽度为0
ttk.Treeview设置宽度为0时,可能仍会渲染列的边框或残留样式缓存,直接移除不需要的列能从根源解决这个问题。修改核心函数如下:
def hide_column(tree, df, styled_window, *columns_to_hide): # 获取需要保留的列 visible_columns = [col for col in df.columns if col not in columns_to_hide] # 更新Treeview的列配置 tree["columns"] = visible_columns # 重新设置表头和列宽度 for col in visible_columns: tree.heading(col, text=col) tree.column(col, width=120, stretch=tk.NO) # 清空现有条目并重新插入仅包含可见列的数据 for item in tree.get_children(): tree.delete(item) for index, row in df.iterrows(): # 只保留可见列的值 values = [row[col] for col in visible_columns] tree.insert("", tk.END, values=values, iid=index) # 恢复选中状态 if hasattr(styled_window, 'selected_index') and styled_window.selected_index in df.index: tree.selection_set(styled_window.selected_index) tree.see(styled_window.selected_index) styled_window.update() tree.update() def show_all_columns(tree, df): # 恢复所有列 tree["columns"] = list(df.columns) for col in df.columns: tree.heading(col, text=col) tree.column(col, width=120, stretch=tk.NO) # 重新插入所有数据 for item in tree.get_children(): tree.delete(item) for index, row in df.iterrows(): values = list(row) tree.insert("", tk.END, values=values, iid=index) # 恢复选中状态 if hasattr(tree.master, 'selected_index'): tree.selection_set(tree.master.selected_index) tree.see(tree.master.selected_index) tree.master.update() tree.update()
2. 清除样式缓存
残留的黄色像素可能来自Treeview的选中样式或旧的tag配置,即使注释了颜色代码,仍可强制清除所有item的tag。在reset_view函数中添加:
# 清除所有条目的tag for item in tree.get_children(): tree.item(item, tags=())
3. 优化视图切换逻辑
将原reset_view函数修改为:
def reset_view(tree, df): show_all_columns(tree, df) # 清除所有条目的tag for item in tree.get_children(): tree.item(item, tags=()) # 恢复选中状态 if hasattr(tree.master, 'selected_index'): tree.selection_set(tree.master.selected_index) tree.see(tree.master.selected_index)
内容的提问来源于stack exchange,提问作者Sld335
相关产品推荐
相关产品推荐

