首页 > 解决方案 > tkinter 按钮破坏框架并从列表中删除索引

问题描述

我对 tkinter 比较陌生,我正在尝试创建一个程序来显示一些股票价值。我让用户输入附加到股票列表的股票代码,并在 tkinter 框架中显示有关股票的一些信息。在框架内,我有一个“删除库存”按钮,我想同时从库存列表中删除库存并销毁该框架。这是我的相关代码:

current_stocks = []
stock_frames = []

def update(): #Update the Currently Displayed Frames
    print(stock_frames)
    for stock in current_stocks:
        list_index = current_stocks.index(stock)
        stock_frame = LabelFrame(root, text=stock, padx=5, pady=5)
        stock_frame.grid(row=list_index+1,column=0,columnspan=3)
        if stock_frame not in stock_frames:
            stock_frames.append(stock_frame)
        stock_info_lbl = Label(stock_frame, text=f'{stock} Current Price')
        stock_info_lbl.grid(row=0,column=0)
        graph_stock_btn = Button(stock_frame, text="Graph", command=graph_stock)
        graph_stock_btn.grid(row=0,column=1)
        remove_stock_btn = Button(stock_frame, text="Remove", command=lambda list_index=list_index: remove_stock(list_index))
        remove_stock_btn.grid(row=0,column=2)

def remove_stock(i): #Remove Stock From List and Destroy the Frame
    current_stocks.pop(i)
    stock_frames[i].destroy()
    stock_frames.pop(i)
    update()

我通过列表索引参数来删除股票,因为据我所见, current_stocks 和 stock_frames 的索引位置应该对应于同一只股票。我尝试使用 grid_forget() 而不是 destroy() 但这并没有改变任何东西。我应该注意,只要我只显示一只股票,我就可以很好地删除它,但是如果我添加不止一只股票,事情就会开始破裂。这让我相信错误与此有关:

    if stock_frame not in stock_frames:
        stock_frames.append(stock_frame)

任何帮助将不胜感激,谢谢!

标签: pythonuser-interfacetkinterlambda

解决方案


你的直觉是正确的,你有问题的代码在哪里,它在if stock_frame not in stock_frames. 这将始终返回 false,因为这是对象比较,LabelFrame即使它们具有相同的文本,两者也不等价。

要解决此问题,您可能只想比较第一个列表 ( ) 中的名称,并认为它具有可以删除的关联条目current_stocks是理所当然的。stock_frames

更彻底的解决方案是使用关联性更强的数据结构,例如dictfromstock_name --> tkinter_frame

看起来像这样:

stocks = {
  "GE": None,  # A default case
  "SYM": tkinter.LabelFrame(...), # A populated value
  ...
}

并且您的 remove 方法将改为对该字典进行操作:

def remove_stock(stock_name): #Remove Stock From List and Destroy the Frame
    stock_frame = stocks[stock_name]
    # stock_frame could be None
    if stock_frame:
        stock_frames[i].destroy()
    del stocks[stock_name]

推荐阅读