如何更新Tkinter Treeview数据且不改变其显示尺寸
Tkinter Treeview重新加载后尺寸异常修复
我开发了一个基于Tkinter的Python应用,功能是读取Excel文件并将数据展示在Treeview组件中。程序启动时Treeview的显示尺寸正常,但当我再次点击按钮重新加载文件时,Treeview的尺寸会发生改变,出现大量未被覆盖的空白区域。
原代码
import pandas as pd from tkinter import * from tkinter import ttk, filedialog import numpy as np import datetime import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg import plotly.express as px def opendir(): filename = filedialog.askopenfilename( initialdir="C:/Inversiones/", title="Open a File", filetype=("xlsx files", "*.xlsx"), ("All Files", "*.*")) LoadDashboard(filename) def buttonopendir(): filename = path LoadDashboard(filename) def loadTable(Filename, SheetName): if Filename: try: filename = r"{}".format(Filename) df = pd.read_excel(filename, sheet_name=SheetName) except ValueError: lblFileStatus.config(text="File Couldn't opened...try again") except FileNotFoundError: lblFileStatus.config(text="File Couldn't found...try again") return df def ONPanel(): filename = path df = loadTable(filename, 'InfoONs') clear_tree(treeDashboard) tickerlist['Tickers'] = list(df['Ticker ARS']) treeDashboard["columns"] = list(df.columns) treeDashboard["show"] = "headings" ColWidth = [70, 70, 230, 115, 40, 50, 45, 70, 80, 80, 120, 80, 80, 80, 30, 40, 115, 100, 70, 60] i = 0 for column in treeDashboard["column"]: treeDashboard.column(column, width=ColWidth[i], stretch=NO) treeDashboard.heading(column, text=column, anchor=W) i += 1 df_rows = df.to_numpy().tolist() for row in df_rows: treeDashboard.insert("", "end", values=row) my_scroll1.config(command=treeDashboard.yview) for col in treeDashboard["columns"]: treeDashboard.heading( col, text=col, command=lambda c=col: sort_treeview(treeDashboard, c, False)) treeDashboard.config(selectmode="extended") treeDashboard.pack() def clear_tree(tree): tree.delete(*tree.get_children()) def sort_treeview(tree, col, descending): data = [(tree.set(item, col), item) for item in tree.get_children('')] data.sort(reverse=descending) for index, (val, item) in enumerate(data): tree.move(item, '', index) tree.heading(col, command=lambda: sort_treeview(tree, col, not descending)) WIDTH = 1800 HEIGHT = 1000 path = 'C:/Inversiones/ONs.xlsx' tickerlist = {} root = Tk() root.title("Obligaciones Negociables") root.geometry(str(WIDTH)+"x"+str(HEIGHT)) # Recuadro para la Pestaña Dashboard my_frame1 = ttk.Frame(root, border=5) my_frame1.pack() # Recuadro para los Botones my_subframe = ttk.Frame(my_frame1) my_subframe.pack() btnOpenExcel = Button(my_subframe, text="Abrir Excel", command=ONPanel) btnOpenExcel.grid(row=0, column=0, padx=30) lblFileStatus = Label(my_subframe, text='Archivo sin actualizar') lblFileStatus.grid(row=0, column=1, padx=30) # Recuadro para el Dashboard my_subframe2 = ttk.Frame(my_frame1, height=500, width=1625) my_subframe2.pack() my_scroll1 = Scrollbar(my_subframe2) my_scroll1.pack(side=RIGHT, fill=Y) treeDashboard = ttk.Treeview( my_subframe2, yscrollcommand=my_scroll1.set, selectmode="extended", height=37) ONPanel() # Configuro el menu my_menu = Menu(root) root.config(menu=my_menu) file_menu = Menu(my_menu, tearoff=False) my_menu.add_cascade(label="File", menu=file_menu) file_menu.add_command(label="Open", command=opendir) root.mainloop()
读取的数据表格
| Ticker ARS | Ticker USD | Empresa | Vencimiento | Ley | Dolar | Pagos | Min Nom | VN colocado | Amortizacion | Industria | Precio USD | Volumen | Precio ARS | MD | TIR | Prox Cupon | Dias Prox Cupon | Dolar MEP | Retorno |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| AEC1O | AEC1D | AES Argentina Generacion S.A | 2025-07-14 00:00:00 | ARG | MEP | Sem | 1 | 30513915 | Bullet | Energia | 107 | 3397074 | 88000 | 1,52 | 5,18 | 2024-01-14 00:00:00 | 78 | 822,43 | 116,02 |
| ARC1O | ARC1D | Aeropuertos Argentina | 2031-08-01 00:00:00 | NY | CABLE | TRI | 1000 | 208949631 | No Bullet | Turismo | 99,4 | 105380784,6 | 83248 | 3,61 | 9,5 | 2023-11-01 00:00:00 | 4 | 837,51 | 144,68 |
| CAC2O | CAC2D | Capex Clase 2 2024 | 2024-05-15 00:00:00 | ARG | CABLE | SEM | 1000 | 300000000 | Bullet | Energia | 108 | 0 | 98000 | 0,54 | -1,96 | 2023-11-15 00:00:00 | 18 | 907,41 | 106,88 |
| CP17O | CP17D | COMPAÑIA GENERAL DE COMBUSTIBLES | 2025-03-08 00:00:00 | NY | CABLE | SEM | 1000 | 196110000 | No Bullet | Energia | 63 | 0 | 54745 | 0,93 | 6 | 2024-03-08 00:00:00 | 132 | 868,97 | 66,77 |
| CP25O | CP25D | COMPAÑIA GENERAL DE COMBUSTIBLES S.A. | 2024-02-25 00:00:00 | ARG | MEP | TRI | 1 | 11287128 | Bullet | Energia | 109,5 | 0 | 99900 | 0,42 | -20,57 | 2023-11-25 00:00:00 | 28 | 912,33 | 101,62 |
问题分析与修复
核心问题
- 重复执行
pack():每次调用ONPanel()都执行treeDashboard.pack(),导致Treeview被多次添加到布局,累积布局规则引发尺寸异常。 - 列配置未重置:重新设置列时没有清除原有列的配置,可能导致旧列的布局参数残留。
- 循环遍历列时的拼写错误:
treeDashboard["column"]应为treeDashboard["columns"](少了复数后缀),导致列宽设置不完整。
修复后的代码
import pandas as pd from tkinter import * from tkinter import ttk, filedialog import numpy as np import datetime import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg import plotly.express as px def opendir(): filename = filedialog.askopenfilename( initialdir="C:/Inversiones/", title="Open a File", filetype=("xlsx files", "*.xlsx"), ("All Files", "*.*")) LoadDashboard(filename) def buttonopendir(): filename = path LoadDashboard(filename) def loadTable(Filename, SheetName): if Filename: try: filename = r"{}".format(Filename) df = pd.read_excel(filename, sheet_name=SheetName) except ValueError: lblFileStatus.config(text="File Couldn't opened...try again") except FileNotFoundError: lblFileStatus.config(text="File Couldn't found...try again") return df def ONPanel(): filename = path df = loadTable(filename, 'InfoONs') clear_tree(treeDashboard) tickerlist['Tickers'] = list(df['Ticker ARS']) # 重置列配置 treeDashboard["columns"] = [] treeDashboard["columns"] = list(df.columns) treeDashboard["show"] = "headings" ColWidth = [70, 70, 230, 115, 40, 50, 45, 70, 80, 80, 120, 80, 80, 80, 30, 40, 115, 100, 70, 60] i = 0 # 修正列遍历的拼写错误 for column in treeDashboard["columns"]: treeDashboard.column(column, width=ColWidth[i], stretch=NO) treeDashboard.heading(column, text=column, anchor=W) i += 1 df_rows = df.to_numpy().tolist() for row in df_rows: treeDashboard.insert("", "end", values=row) my_scroll1.config(command=treeDashboard.yview) for col in treeDashboard["columns"]: treeDashboard.heading( col, text=col, command=lambda c=col: sort_treeview(treeDashboard, c, False)) treeDashboard.config(selectmode="extended") # 移除重复的pack()调用 def clear_tree(tree): tree.delete(*tree.get_children()) def sort_treeview(tree, col, descending): data = [(tree.set(item, col), item) for item in tree.get_children('')] data.sort(reverse=descending) for index, (val, item) in enumerate(data): tree.move(item, '', index) tree.heading(col, command=lambda: sort_treeview(tree, col, not descending)) WIDTH = 1800 HEIGHT = 1000 path = 'C:/Inversiones/ONs.xlsx' tickerlist = {} root = Tk() root.title("Obligaciones Negociables") root.geometry(str(WIDTH)+"x"+str(HEIGHT)) # Recuadro para la Pestaña Dashboard my_frame1 = ttk.Frame(root, border=5) my_frame1.pack() # Recuadro para los Botones my_subframe = ttk.Frame(my_frame1) my_subframe.pack() btnOpenExcel = Button(my_subframe, text="Abrir Excel", command=ONPanel) btnOpenExcel.grid(row=0, column=0, padx=30) lblFileStatus = Label(my_subframe, text='Archivo sin actualizar') lblFileStatus.grid(row=0, column=1, padx=30) # Recuadro para el Dashboard my_subframe2 = ttk.Frame(my_frame1, height=500, width=1625) my_subframe2.pack() my_scroll1 = Scrollbar(my_subframe2) my_scroll1.pack(side=RIGHT, fill=Y) treeDashboard = ttk.Treeview( my_subframe2, yscrollcommand=my_scroll1.set, selectmode="extended", height=37) # 初始化时只执行一次pack() treeDashboard.pack(fill=BOTH, expand=True) ONPanel() # Configuro el menu my_menu = Menu(root) root.config(menu=my_menu) file_menu = Menu(my_menu, tearoff=False) my_menu.add_cascade(label="File", menu=file_menu) file_menu.add_command(label="Open", command=opendir) root.mainloop()
关键改动说明
- 移除重复的
pack():只在初始化Treeview时执行一次treeDashboard.pack(fill=BOTH, expand=True),后续更新数据不再调用。 - 重置列配置:在设置新列前先执行
treeDashboard["columns"] = [],清除原有列的配置,避免参数残留。 - 修正列遍历拼写错误:将
treeDashboard["column"]改为treeDashboard["columns"],确保所有列都能正确设置宽度。 - 优化布局填充:初始化时给
pack()添加fill=BOTH, expand=True,让Treeview自适应父容器尺寸。
内容的提问来源于stack exchange,提问作者Nando7789
相关产品推荐
相关产品推荐

