You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何更新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 ARSTicker USDEmpresaVencimientoLeyDolarPagosMin NomVN colocadoAmortizacionIndustriaPrecio USDVolumenPrecio ARSMDTIRProx CuponDias Prox CuponDolar MEPRetorno
AEC1OAEC1DAES Argentina Generacion S.A2025-07-14 00:00:00ARGMEPSem130513915BulletEnergia1073397074880001,525,182024-01-14 00:00:0078822,43116,02
ARC1OARC1DAeropuertos Argentina2031-08-01 00:00:00NYCABLETRI1000208949631No BulletTurismo99,4105380784,6832483,619,52023-11-01 00:00:004837,51144,68
CAC2OCAC2DCapex Clase 2 20242024-05-15 00:00:00ARGCABLESEM1000300000000BulletEnergia1080980000,54-1,962023-11-15 00:00:0018907,41106,88
CP17OCP17DCOMPAÑIA GENERAL DE COMBUSTIBLES2025-03-08 00:00:00NYCABLESEM1000196110000No BulletEnergia630547450,9362024-03-08 00:00:00132868,9766,77
CP25OCP25DCOMPAÑIA GENERAL DE COMBUSTIBLES S.A.2024-02-25 00:00:00ARGMEPTRI111287128BulletEnergia109,50999000,42-20,572023-11-25 00:00:0028912,33101,62

问题分析与修复

核心问题

  1. 重复执行pack():每次调用ONPanel()都执行treeDashboard.pack(),导致Treeview被多次添加到布局,累积布局规则引发尺寸异常。
  2. 列配置未重置:重新设置列时没有清除原有列的配置,可能导致旧列的布局参数残留。
  3. 循环遍历列时的拼写错误: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()

关键改动说明

  1. 移除重复的pack():只在初始化Treeview时执行一次treeDashboard.pack(fill=BOTH, expand=True),后续更新数据不再调用。
  2. 重置列配置:在设置新列前先执行treeDashboard["columns"] = [],清除原有列的配置,避免参数残留。
  3. 修正列遍历拼写错误:将treeDashboard["column"]改为treeDashboard["columns"],确保所有列都能正确设置宽度。
  4. 优化布局填充:初始化时给pack()添加fill=BOTH, expand=True,让Treeview自适应父容器尺寸。

内容的提问来源于stack exchange,提问作者Nando7789

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 05:27:04