Python tkinter列表框未使用跟踪()更新

Python tkinter列表框未使用跟踪()更新,python,tkinter,Python,Tkinter,基本上,我试图在tkinter中创建一个搜索框,您可以在其中尝试输入框中的内容,并在下面的列表框中显示包含您键入内容的特定列表中的所有内容。我从你那里得到了初始代码 但是,由于我不太了解课程,我决定将其缩短为: from tkinter import * root = Tk() def update_list(*args): search_term = search_var.get() # Just a generic list to populate the listbo

基本上,我试图在tkinter中创建一个搜索框,您可以在其中尝试输入框中的内容,并在下面的列表框中显示包含您键入内容的特定列表中的所有内容。我从你那里得到了初始代码

但是,由于我不太了解课程,我决定将其缩短为:

from tkinter import *

root = Tk()

def update_list(*args):
    search_term = search_var.get()

    # Just a generic list to populate the listbox
    lbox_list = ['Adam', 'Lucy', 'Barry', 'Bob',
                 'James', 'Frank', 'Susan', 'Amanda', 'Christie']

    lbox.delete(0, END)

    for item in lbox_list:
        if search_term.lower() in item.lower():
            lbox.insert(END, item)


# searchbar
search_var = StringVar()
search_var.trace("w", update_list)
entry = Entry(root,textvariable=search_var, width=13)
lbox = Listbox(root, width=45, height=15)
entry.grid(row=1, column=0, padx=2, pady=3)
lbox.grid(row=2, column=0, rowspan=20, padx=2, pady=3)
update_list()

root.mainloop()
这段代码运行得很好,所以我决定将它应用到我的实际程序中,这就是我遇到问题的地方

def main():
    # searchbar
    search_var = StringVar()
    entry = Entry(root,textvariable=search_var, width=13)
    lbox = Listbox(root, width=40, height=15)
    entry.grid(row=1, column=0, padx=2, pady=3)
    lbox.grid(row=2, column=0, padx=2, pady=3)
    search_var.trace("w", update_list)
    update_list(search_var,lbox)
def update_list(search_var,lbox):
    search_term = search_var.get()
    print(search_term)

    # Just a generic list to populate the listbox
    lbox_list = ['Adam', 'Lucy', 'Barry', 'Bob',
                 'James', 'Frank', 'Susan', 'Amanda', 'Christie']

    lbox.delete(0, END)

    for item in lbox_list:
        if search_term.lower() in item.lower():
            lbox.insert(END, item)

# main window (menu)
root = Tk()
main()
root.mainloop()

我遇到的问题是列表框不更新。任何帮助都将不胜感激。

您的问题是,
search\u var
main
函数完成时过期,因此,您告诉它执行的任何更新也将过期。@acw1668解决方案之所以有效,是因为
lambda
使引用保持活动状态。这也可以通过
global
关键字来实现,尽管我更喜欢acw1668的方法,因为它提供了少量的封装。然而,滥用
lambda
仅仅为了保持任意引用的活跃性并不是一个好的设计选择。另外,如果在循环中使用多个重复引用执行此操作,因为
lambda
当前处于状态,则只有最后一个引用将保持活动状态

这就是全球方法的样子

from tkinter import *

root = Tk()

def main():
    global search_var
    search_var = StringVar()
    
    entry = Entry(root, textvariable=search_var, width=13)
    entry.grid(padx=2, pady=3)

    global lbox
    lbox = Listbox(root, width=40, height=15)
    lbox.grid(padx=2, pady=3)

    search_var.trace("w", update_list)
    update_list(lbox)    
    
    
def update_list(*args):
    search_term = search_var.get()

    lbox_list = ['Adam', 'Lucy', 'Barry', 'Bob',
                 'James', 'Frank', 'Susan', 'Amanda', 'Christie']

    lbox.delete(0, END)
    
    for item in lbox_list:
        if search_term.lower() in item.lower():
            lbox.insert(END, item)

main() 
root.mainloop()
我注意到你说你这样做是因为你需要在将来再次得到这个显示器。这意味着您打算在某个时候取消此显示。当你没有引用任何你刚刚制作的小部件时,你打算怎么做?您的设计存在很大缺陷,而且
lambda
无法帮助您改进。也许你想考虑一个设计,实际上给你一点点的控制。
import tkinter as tk

root = tk.Tk()

def search_frame(row=0, column=0):
    frame = tk.Frame(root)
    frame.grid(row=row, column=column)
    
    def update_list(*args):
        search_term = entry.var.get()

        lbox_list = ['Adam', 'Lucy', 'Barry', 'Bob',
                     'James', 'Frank', 'Susan', 'Amanda', 'Christie']

        lbox.delete(0, tk.END)
    
        for item in lbox_list:
            if search_term.lower() in item.lower():
                lbox.insert(tk.END, item)
                
    entry     = tk.Entry(frame, width=13)
    entry.var = tk.StringVar()
    entry.var.trace("w", update_list)
    entry.configure(textvariable=entry.var)
    entry.grid(padx=2, pady=3)

    lbox = tk.Listbox(frame, width=40, height=15)
    lbox.grid(padx=2, pady=3)

    update_list()
    
    return frame
    
searchframe = search_frame()

root.mainloop()

两者有什么区别?您给它起了一个名为
main
,它只会被调用一次。你使它比第一次更复杂one@Karthik我需要能够在将来再次执行main()的内容,这就是我将其作为函数的原因。问题源于在函数中创建搜索栏,但是我不知道为什么,也不知道如何修复它,因为我需要在函数中使用它。请尝试将
search\u var.trace(“w”,update\u list)
更改为
search\u var.trace(“w”,lambda*args:update\u list(search\u var,lbox))
@acw1668谢谢您的完美工作!介意解释一下它是如何工作的或者链接一个这样的网站吗?我想很可能
search\u var
main()
函数中的一个局部变量。因此,使用
search\u var.trace(“w”,update\u list)
并不明确表示
search\u var
main()
返回后被引用,它可能被垃圾收集。但是,使用
search\u var.trace(“w”,lambda*args:update\u list(search\u var,lbox))
明确显示
search\u var
main()
返回后仍会被引用。感谢您提供的详细答案。我在main()的开头使用root.winfo_children():widget.destroy()``中的widget来刷新它,而不是去掉显示,然后重新构建它。这是因为根据用户的操作,根窗口将被更改。我确实考虑过这一点,但我最初的实现是
search\u var.trace(“w”,lambda search\u var,lbox:update\u list(search\u var,lbox))
,但我无法获得正确的输出,所以我像nvm一样,但是
*args
起到了作用。@Friend\u Slayer666~看看我在答案底部附加了什么。直到你可以在函数中定义函数为止。我非常喜欢你的代码。感谢您的帮助:)@Friend\u Slayer666~关于“我非常喜欢您的代码”。谢谢,但不是很好。所有这些程序编程的东西都是一团糟。如果我为自己写这篇文章,
defsearch\u frame
将是
classsearchframe
。它将是非常通用、动态和可重用的,我再也不用写它了,但我可以在任何地方使用它。就像您使用
条目
标签
等一样。。什么都可以。