How to set the text/value/content of an `Entry` widget using a button in tkinter
Asked Answered
S

6

61

I am trying to set the text of an Entry widget using a button in a GUI using the tkinter module.

This GUI is to help me classify thousands of words into five categories. Each of the categories has a button. I was hoping that using a button would significantly speed me up and I want to double check the words every time otherwise I would just use the button and have the GUI process the current word and bring the next word.

The command buttons for some reason are not behaving like I want them to. This is an example:

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()

So far, when I am able to compile, the click does nothing.

Stetson answered 4/5, 2013 at 11:42 Comment(0)
H
119

You might want to use insert method. You can find the documentation for the Tkinter Entry Widget here.

This script inserts a text into Entry. The inserted text can be changed in command parameter of the Button.

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()
Happening answered 4/5, 2013 at 12:24 Comment(2)
Just want to say to newcomers, that you may have import tkinter as tk, so, the line with e.delete(0,END) becomes e.delete(0,tk.END).Defilade
@m3nda: True, by even when using import tkinter as tk, it's still often convenient to follow it with a from tkinter.constants import * to avoid having the prefix the many constants in the module defines with tk. — although you can also just use a literal string instead which doesn't require importing anything. i.e. e.delete(0,'end') or e.delete(0,'END').Mccollough
F
40

If you use a "text variable" tk.StringVar(), you can just set() that.

No need to use the Entry delete and insert. Moreover, those functions don't work when the Entry is disabled or readonly! The text variable method, however, does work under those conditions as well.

import Tkinter as tk

...

entry_text = tk.StringVar()
entry = tk.Entry( master, textvariable=entry_text )
entry_text.set( "Hello World" )
Flowerpot answered 2/2, 2016 at 23:21 Comment(3)
But if I already have an Entry object, how do I get its StringVar object?Decrepitate
I guess you don't want to keep your StringVar in scope? I can see that... Well, check out this SO thread: #3222408 That shows how to get the attributes of a Tk Widget through a couple of means. I didn't test it, but you should be able to access the textvariable that way.Flowerpot
BuvinJ: If you have to first call cget() to get the StringVar associated with the Entry widget, it kind of defeats the purpose of using one in this scenario IMO. Also, when you're responding to someone else's comment, you should put @ + their username in it (which you didn't do for @Madlozoz's). Regardless, I think this is a good answer.Mccollough
B
25

You can choose between the following two methods to set the text of an Entry widget. For the examples, assume imported library import tkinter as tk and root window root = tk.Tk().


  • Method A: Use delete and insert

    Widget Entry provides methods delete and insert which can be used to set its text to a new value. First, you'll have to remove any former, old text from Entry with delete which needs the positions where to start and end the deletion. Since we want to remove the full old text, we start at 0 and end at wherever the end currently is. We can access that value via END. Afterwards the Entry is empty and we can insert new_text at position 0.

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

  • Method B: Use StringVar

    You have to create a new StringVar object called entry_text in the example. Also, your Entry widget has to be created with keyword argument textvariable. Afterwards, every time you change entry_text with set, the text will automatically show up in the Entry widget.

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

  • Complete working example which contains both methods to set the text via Button:

    This window

    screenshot

    is generated by the following complete working example:

    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()
    
Bastien answered 4/1, 2019 at 13:36 Comment(2)
Can you state the advantages and disadvantages of each method? Why would one choose one over the other?Sampson
What does this add to the conversation other than more examples? You've simply recycled the top two answers, posted years prior to this.Flowerpot
D
3

Your problem is that when you do this:

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

it tries to evaluate what to set for the command. So when instantiating the Button object, it actually calls setText("plant"). This is wrong, because you don't want to call the setText method yet. Then it takes the return value of this call (which is None), and sets that to the command of the button. That's why clicking the button does nothing, because there is no command set for it.

If you do as Milan Skála suggested and use a lambda expression instead, then your code will work (assuming you fix the indentation and the parentheses).

Instead of command=setText("plant"), which actually calls the function, you can set command=lambda:setText("plant") which specifies something which will call the function later, when you want to call it.

If you don't like lambdas, another (slightly more cumbersome) way would be to define a pair of functions to do what you want:

def set_to_plant():
    set_text("plant")
def set_to_animal():
    set_text("animal")

and then you can use command=set_to_plant and command=set_to_animal - these will evaluate to the corresponding functions, but are definitely not the same as command=set_to_plant() which would of course evaluate to None again.

Dalesman answered 8/6, 2018 at 9:28 Comment(0)
O
1

One way would be to inherit a new class,EntryWithSet, and defining set method that makes use of delete and insert methods of the Entry class objects:

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()
Outline answered 13/2, 2018 at 22:49 Comment(0)
N
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)
News answered 23/7, 2019 at 16:29 Comment(1)
If You want to put the Location Of a Image in Entry WidgetNews

© 2022 - 2024 — McMap. All rights reserved.