Textbox (Entry) in Tk (tkinter)

A textbox lets the user enter any one-line text. In Tk it is represented by the ttk.Entry class, which inherits the features of a more primitive widget called tk.Entry.

Widget creation

To create a textbox let's first create an instance of the ttk.Entry class.

import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.config(width=300, height=200)
# Create the textbox.
entry = ttk.Entry(root)
# Place it within the window.
entry.place(x=50, y=50)
root.mainloop()

This code creates the following interface:

/images/textbox-entry-in-tk-tkinter/tk-entry.png

As with all widgets, the first argument indicates the parent control. In this case, the parent is the root window, which is also the default value, so it could be omitted.

To specify the text alignment, we use the justify param. Valid values for this param are tk.LEFT (default value), tk.RIGHT and tk.CENTER.

# Right justify text.
entry = ttk.Entry(root, justify=tk.RIGHT)

We can force Tk to show a custom glyph when we want to hide the text; for example, when the widget is used to enter a password.

# Show asterisks instead of the original text.
entry = ttk.Entry(root, show="*")

Through the width param we indicate the widget width, although not in pixels, but in characters. For example, the following code establishes enough width to view a 10-characters line completely.

entry = ttk.Entry(root, width=10)

If the text exceeds the specified amount of characters, the widget always shows a piece of the text (as long as width) based on the cursor position. Since the width of each character might change even in the same typography, the width value is always an approximate value, not an absolute one.

A textbox might be created as disabled (grayed out and the user can't type in it) using the state param.

entry = ttk.Entry(root, state=tk.DISABLED)

We can enable it later by establishing again this param via the config() method.

entry.config(state=tk.NORMAL)

An intermediate state is "readonly", in which the user can see the widget but can not type in it.

entry = ttk.Entry(root, state="readonly")

This is specially useful when we want to disable text entering but nevertheless keep copying options or contextual menus.

Main operations

Once the textbox is created, we can execute the following operations: insert, get, select, and delete text. From these, the most used is the second one, since it let us know what the user of our application has typed in.

So let's begin by fetching what the user has typed inside the textbox using the get() method.

print(entry.get())

For example, the following code outputs the typed text when the user presses a button.

entry.insert(0, "Hello world!")
entry.place(x=50, y=50)
button = ttk.Button(root, text="Get text",
     command=lambda: print(entry.get()))
button.place(x=50, y=100)

Inversely, to write text we use insert(), that takes a position as the first argument and a regular string as the second one.

entry.insert(0, "Hello world!")

This is similar to:

entry.insert(0, "Hello")
entry.insert(5, " world!")

Every Tk function that requires a position will accept the tk.END constant, used to represent the end of the text. So here tk.END equals len(entry.get()). For this reason the following code also gets the same result as the previous ones.

entry.insert(0, "Hello")
entry.insert(tk.END, " world!")

We can delete a text or a piece of it by using the delete() method, which receives as arguments the indexes of the range of characters we want to delete.

# Deletes the whole text.
entry.delete(0, tk.END)

In the same way works select_range(), that selects the text from one position to another one. For example, the following code selects "world".

entry.insert(0, "Hello world!")
# Select from the sixth character to the eleventh.
entry.select_range(6, 11)
# Send the focus to the textbox to make effective
# the selection.
entry.focus()

To get the cursor position within the textbox, we call the index() method with the tk.INSERT constant.

print(entry.index(tk.INSERT))

And to set the position of the cursor:

entry.insert(0, "Hello world!")
# Sets the cursor before the "w".
entry.icursor(6)
# Sends the focus.
entry.focus()

Tk has no specific function to return the selected text, but by using the index() method with the tk.SEL_FIRST and tk.SEL_LAT constants (which retrieve the start and end indexes of the selection) we can manually build it.

entry.insert(0, "Hello world!")
def get_selection():
     # First check there's a selection.
     if entry.select_present():
         # Get the selection start and end indexes
         first = entry.index(tk.SEL_FIRST)
         last = entry.index(tk.SEL_LAST)
         print(entry.get()[first:last])
     else:
         print("There is no selection.")
button = ttk.Button(root, text="Get selection",
                     command=get_selection)

The select_present() method returns a boolean that indicates where there is a selection at all.

Linking a variable

When a textbox is simply employed to receive a text entered by the user, then it will be enough to call the get() method to obtaint the text when we need it, as previously exposed. But when our application requires to both read the user input and write new text into the textbox very often, then it would be more suitable to link a variable.

Tk provides the tk.StringVar() to create objects that act like a string, but in order to assign or read a value we need to use the set() and get() methods.

var = tk.StringVar()
var.set("Hello world!")
print(var.get())

We can link one of these variables to a textbox when creating an instance of ttk.Entry via the textvariable param.

entry_var = tk.StringVar()
entry = ttk.Entry(root, textvariable=entry_var)

This way, every call to entry_var.set() will modify the textbox content, and inversely, changes made by the user in the widget will alterate the result of entry_var.get().