简体   繁体   English

为什么 Tkinter 条目的 get function 没有返回任何东西?

[英]Why doesn't Tkinter Entry's get function return anything?

I'm trying to use two dialogs to get manual input, and then work with that data.我正在尝试使用两个对话框来获取手动输入,然后使用该数据。
All source I've found claim I should use the get() function, but I wrote a simple mini program yet, and I can't make the second dialog work.我找到的所有来源都声称我应该使用get() function,但我还编写了一个简单的小程序,我无法使第二个对话框工作。
I hope someone can tell me what I'm doing wrong.我希望有人能告诉我我做错了什么。 Here's a file:这是一个文件:

from tkinter import *
from tkinter.filedialog import askdirectory
from tkinter import messagebox

def getpath():
    def selectPath():
        path_ = askdirectory()
        path.set(path_)
    root = Tk()
    root.title('select path')
    path = StringVar()
    def close():
        if(path.get()==""):
            messagebox.showinfo("","nothing")
        else:
            root.withdraw()
            root.quit()
    Label(root,text="path:").grid(row=0,column=0)
    Entry(root,textvariable = path).grid(row=0,column=1)
    Button(root,text="select",command=selectPath).grid(row=0,column=2)
    Button(root,text="enter",command=close).grid(row=0,column=3)
    root.mainloop()
    return path.get()

def getname():
    def get_need_name():
        name = need_name.get()
        print('hereherehere'+name) #does not work
    root = Tk()
    root.title('select name')
    need_name = StringVar()
    Label(root,text="name:").grid(row=0,column=0)
    entry = Entry(root,bd=10,textvariable=need_name)
    entry.grid(row=0,column=1)
    Button(root,text="enter", font=16, bg="silver", relief='groove', command=get_need_name).grid(row=0,column=2)
    root.mainloop()
    return name.get()

def main():
    path = getpath()
    print("mypath:"+path)
    print('******************')
    print('done!')
    name = getname()
    print("myname:"+name)

if __name__ == '__main__':
    main()

This give me two dialogs I can type in, but only the first dialog works.这给了我两个可以输入的对话框,但只有第一个对话框有效。

The reason is that you are creating multiple instances of Tk, and you don't destroy the instances when you are done with them.原因是您正在创建 Tk 的多个实例,并且在完成它们后不会销毁这些实例。 This causes two problems.这导致两个问题。 First is a memory leak.首先是 memory 泄漏。 Each time you call one of these functions you create a new window and a new tcl interpreter.每次调用其中一个函数时,都会创建一个新的 window 和一个新的 tcl 解释器。

The second problem is that the first root window becomes the default window when a root isn't specified.第二个问题是,当未指定根时,第一个根 window 成为默认值 window。 When you create a StringVar in the second function, because you didn't specify which root window it belongs to it will be assigned to the first root window. When you use it as the target of textvariable in a second instance of Tk , tkinter thinks the variable doesn't exist so it creates a new one for the second window. However, your reference is still to the one created in the first root window and is never updated by user input in the second window.当您在第二个 function 中创建一个StringVar时,因为您没有指定它属于哪个根 window,它将被分配给第一个根 window。当您在Tk的第二个实例中将它用作textvariable的目标时,tkinter 认为该变量不存在,因此它为第二个 window 创建一个新变量。但是,您的引用仍然是在第一个根 window 中创建的,并且永远不会被第二个 window 中的用户输入更新。

Confusing?令人困惑? Yes, which is why you typically shouldn't be creating more than one instance of Tk .是的,这就是为什么您通常不应创建多个Tk实例的原因。

To make your code work with as few changes as possible and to remove the memory leak caused by not destroying the windows, you can change the last couple of lines in your method to look like the following.为了使您的代码在尽可能少的更改下工作并消除因未破坏 windows 而导致的 memory 泄漏,您可以将方法中的最后几行更改为如下所示。 This destroys the root window when you are done with it, removing the memory leak and the side effect of having more than one root window.当你用完它时,这会破坏根 window,消除 memory 泄漏和拥有多个根 window 的副作用。

root = Tk()
...
root.mainloop()
value = path.get()
root.destroy()
return value

The second dialog should look similar:第二个对话框看起来应该类似:

root = Tk()
...
root.mainloop()
value = name.get()
root.destroy()
return value

This retrieves the value after mainloop exits but before the underlying tcl interpreter is deleted, and then destroys the window and its tcl interpreter.这会在mainloop退出后但在删除底层 tcl 解释器之前检索值,然后销毁 window 及其 tcl 解释器。

The next time you create an instance of Tk , that instance will become the new default root, and any new instance of StringVar will go to that root.下次您创建Tk的实例时,该实例将成为新的默认根,并且StringVar的任何新实例都将 go 指向该根。

Another solution would be to specify the master for the StringVar instance, but that leaves the memory leak in place so it's only half of a solution.另一种解决方案是为StringVar实例指定主实例,但这会留下 memory 泄漏,因此它只是解决方案的一半。

Arguably a better solution is to create a single root window, and either reuse it or create instances of Toplevel rather than Tk .可以说,更好的解决方案是创建单个根 window,然后重用它或创建Toplevel而不是Tk的实例。 Effbot has some decent documentation on how to create a modal window with wait_window . Effbot有一些关于如何使用wait_window创建模式 window 的不错的文档。

After some testing, and googling the root.quit() is the problem here is a working example for you to look at and mess with.经过一些测试,并用谷歌搜索root.quit()是这里的问题,这是一个供您查看和处理的工作示例。

from tkinter import *
from tkinter.filedialog import askdirectory
from tkinter import messagebox

root = Tk()
path = StringVar()
def select_path():
    #uses the return value to set no need to create an additional variable
    path.set(askdirectory())
def close():
    if path.get() == "":
        messagebox.showinfo("","Please select path")
    else:
        get_name_frame.tkraise()
def get_name():
    print("hereherehere", name.get())


get_path_frame = Frame(root)
get_path_frame.grid(row=0, column=0, sticky="nsew")
Label(get_path_frame,text="path:").grid(row=0,column=0)
Entry(get_path_frame,textvariable = path).grid(row=0,column=1)
Button(get_path_frame,text="select",command=select_path).grid(row=0,column=2)
Button(get_path_frame,text="enter",command=close).grid(row=0,column=3)

get_name_frame = Frame(root)
get_name_frame.grid(row=0, column=0,sticky="nsew")
Label(get_name_frame, text="name: ").grid(row=0, column=0)
name = StringVar()
entry = Entry(get_name_frame, bd=10, textvariable = name)
entry.grid(row=0, column=1)
Button(get_name_frame,text="enter", font=16, bg="silver", relief='groove', command=get_name).grid(row=0,column=2)

get_path_frame.tkraise()
root.mainloop()


声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM