如何使用tkinter中的按钮设置`Entry`小部件的文本/值/内容

57

我正在尝试使用tkinter模块中的一个按钮来设置GUI中Entry小部件的文本。

这个GUI是为了帮助我将数千个单词分类到五个类别中。每个类别都有一个按钮。我希望使用按钮可以显著提高我的速度,并且我想在每次分类单词时进行双重检查,否则我会只使用按钮并让GUI处理当前单词并带出下一个单词。

某些原因导致命令按钮的行为不像我想要的那样。以下是一个示例:

import tkinter as tk
from tkinter import ttk

win = tk.Tk()

v = tk.StringVar()
def setText(word):
    v.set(word)

a = ttk.Button(win, text="plant", command=setText("plant"))
a.pack()
b = ttk.Button(win, text="animal", command=setText("animal"))
b.pack()
c = ttk.Entry(win, textvariable=v)
c.pack()
win.mainloop()

到目前为止,当我能够编译时,点击没有任何反应。

6个回答

115

你可能想要使用insert方法。在这里可以找到Tkinter Entry小部件的文档。

该脚本将文本插入Entry中。插入的文本可以在按钮的command参数中更改。

from tkinter import *

def set_text(text):
    e.delete(0,END)
    e.insert(0,text)
    return

win = Tk()

e = Entry(win,width=10)
e.pack()

b1 = Button(win,text="animal",command=lambda:set_text("animal"))
b1.pack()

b2 = Button(win,text="plant",command=lambda:set_text("plant"))
b2.pack()

win.mainloop()

30
对于新手来说,我想说的是,你可能会使用import tkinter as tk,因此带有e.delete(0,END)的那一行要改成e.delete(0,tk.END) - m3nda
4
@m3nda:确实,即使使用import tkinter as tk,在其后面加上from tkinter.constants import *通常也很方便,以避免在使用该模块定义的许多常量时需要添加前缀tk.。但是你也可以直接使用字面字符串,无需导入任何内容。例如,e.delete(0,'end')e.delete(0,'END') - martineau

38

如果您使用“文本变量”tk.StringVar(),则只需使用set()即可。

无需使用Entry的删除和插入功能。此外,当Entry被禁用或只读时,这些函数不起作用!但是,文本变量方法在这些情况下也可以工作。

import Tkinter as tk

...

entry_text = tk.StringVar()
entry = tk.Entry( master, textvariable=entry_text )
entry_text.set( "Hello World" )

但是如果我已经有一个“Entry”对象,如何获取它的“StringVar”对象呢? - Madlozoz
1
我猜你不想保留你的StringVar在作用域内?我能理解...好吧,看看这个SO线程:https://dev59.com/yXA75IYBdhLWcg3wkZ-A 它展示了如何通过几种方式获取Tk Widget的属性。虽然我没有测试过,但你应该可以通过那种方式访问textvariable - BuvinJ
1
BuvinJ:如果你必须先调用cget()才能获取与Entry小部件关联的StringVar,在我看来,这有点违背了在此情况下使用它的目的。另外,当你回复别人的评论时,你应该在其中加上@ +他们的用户名(你没有给@Madlozoz加上)。不管怎样,我认为这是一个好答案。 - martineau

24
您可以选择以下两种方法之一来设置Entry小部件的文本。在示例中,假设导入库import tkinter as tk并创建了根窗口root = tk.Tk()
  • 方法A:使用deleteinsert

    Entry小部件提供了可以用于将其文本设置为新值的deleteinsert方法。首先,您需要使用delete删除Entry中以前的旧文本,需要提供删除的起始和结束位置。因为我们想要删除全旧文本,所以我们从0开始,并在当前结尾处结束,可以通过END访问该值。然后Entry就是空的,我们可以在位置0插入new_text

    entry = tk.Entry(root)
    new_text = "Example text"
    entry.delete(0, tk.END)
    entry.insert(0, new_text)
    

  • 方法 B:使用 StringVar

    在这个例子中,您需要创建一个名为 entry_text 的新的 StringVar 对象。同时,您的 Entry 组件必须使用关键字参数 textvariable 创建。之后,每当您使用 set 更改 entry_text 时,文本将自动显示在 Entry 组件中。

entry_text = tk.StringVar()
entry = tk.Entry(root, textvariable=entry_text)
new_text = "Example text"
entry_text.set(new_text)

  • 包含使用 Button 设置文本的两种方法的完整工作示例:

    这个窗口:

    screenshot

    是由以下完整的工作示例生成的:

import tkinter as tk

def button_1_click():
    # define new text (you can modify this to your needs!)
    new_text = "Button 1 clicked!"
    # delete content from position 0 to end
    entry.delete(0, tk.END)
    # insert new_text at position 0
    entry.insert(0, new_text)

def button_2_click():
    # define new text (you can modify this to your needs!)
    new_text = "Button 2 clicked!"
    # set connected text variable to new_text
    entry_text.set(new_text)

root = tk.Tk()

entry_text = tk.StringVar()
entry = tk.Entry(root, textvariable=entry_text)

button_1 = tk.Button(root, text="Button 1", command=button_1_click)
button_2 = tk.Button(root, text="Button 2", command=button_2_click)

entry.pack(side=tk.TOP)
button_1.pack(side=tk.LEFT)
button_2.pack(side=tk.LEFT)

root.mainloop()

你能说明每种方法的优缺点吗?为什么会选择其中一种而不是另一种? - Al Lelopath
1
除了更多的例子之外,这句话还有什么可以增加对话的内容吗?你只是简单地回收了两个在几年前发布的顶级答案。 - BuvinJ

3

您的问题在于当您执行以下操作时:

a = Button(win, text="plant", command=setText("plant"))

它试图评估要为命令设置什么。因此,在实例化Button对象时,实际上调用了setText("plant")。这是错误的,因为您不想立即调用setText方法。然后它获取此调用的返回值(即None),并将其设置为按钮的命令。这就是为什么单击按钮不起作用的原因,因为没有为其设置命令。
如果按照Milan Skála建议的使用lambda表达式,则您的代码将起作用(假设您修复缩进和括号)。
与实际调用函数的command=setText("plant")不同,您可以设置command=lambda:setText("plant"),该指定稍后将调用函数的内容。
如果您不喜欢lambda,另一种(略微麻烦)的方法是定义一对函数来执行您想要的操作:
def set_to_plant():
    set_text("plant")
def set_to_animal():
    set_text("animal")

然后你可以使用command=set_to_plantcommand=set_to_animal - 这些将评估为相应的函数,但绝对不同于command=set_to_plant(),后者当然会再次评估为None


1
一种方法是继承一个新类EntryWithSet,并定义一个set方法,利用deleteinsert方法来操作Entry类对象:
try:                        # In order to be able to import tkinter for
    import tkinter as tk    # either in python 2 or in python 3
except ImportError:
    import Tkinter as tk


class EntryWithSet(tk.Entry):
    """
    A subclass to Entry that has a set method for setting its text to
    a given string, much like a Variable class.
    """

    def __init__(self, master, *args, **kwargs):
        tk.Entry.__init__(self, master, *args, **kwargs)


    def set(self, text_string):
        """
        Sets the object's text to text_string.
        """

        self.delete('0', 'end')
        self.insert('0', text_string)


def on_button_click():
    import random, string
    rand_str = ''.join(random.choice(string.ascii_letters) for _ in range(19))
    entry.set(rand_str)


if __name__ == '__main__':
    root = tk.Tk()
    entry = EntryWithSet(root)
    entry.pack()
    tk.Button(root, text="Set", command=on_button_click).pack()
    tk.mainloop()

1
e= StringVar()
def fileDialog():
    filename = filedialog.askopenfilename(initialdir = "/",title = "Select A 
    File",filetype = (("jpeg","*.jpg"),("png","*.png"),("All Files","*.*")))
    e.set(filename)
la = Entry(self,textvariable = e,width = 30).place(x=230,y=330)
butt=Button(self,text="Browse",width=7,command=fileDialog).place(x=430,y=328)

1
如果您想将图像的位置放置在输入小部件中 - Kishore Sharma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接