Caja de texto (Entry) en Tcl/Tk (tkinter)

Caja de texto (Entry) en Tcl/Tk (tkinter)

Una caja de texto permite al usuario ingresar cualquier texto de una línea. En Tcl/Tk está representada a través de la clase ttk.Entry, que a su vez hereda la funcionalidad de un control más primitivo llamado tk.Entry (para la diferencia entre los módulos tk y ttk véase este artículo).

Para crear una caja de texto, entonces, vamos a crear una instancia de la primera clase.

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
root.config(width=300, height=200)
# Crear caja de texto.
entry = ttk.Entry()
# Posicionarla en la ventana.
entry.place(x=50, y=50)
root.mainloop()

Caja de texto en Tcl/Tk

Para especificar la justificación del texto, esto es, si debe alinearse a la izquierda, derecha o el centro, indicamos el parámetro justify, cuyos valores pueden ser, respectivamente, tk.LEFT (por defecto), tk.RIGHT y tk.CENTER.

# Justificar el texto a la derecha.
entry = ttk.Entry(justify=tk.RIGHT)

Podemos hacer que la caja de texto muestre un glifo en particular cuando queremos ocultar el texto a simple vista; por ejemplo, si el control es empleado para escribir una contraseña.

# Mostrar asteriscos en lugar del texto original.
entry = ttk.Entry(show="*")

A través del parámetro width indicamos el ancho del control, pero no en píxeles, sino en caracteres. Por ejemplo, el siguiente código establece un ancho suficiente para visualizar una línea de 10 caracteres completamente.

entry = ttk.Entry(width=10)

Si el texto excede la cantidad de caracteres especificados, el control siempre muestra una porción de él de dicho tamaño, según la posición del cursor. Puesto que el ancho de cada carácter puede variar aun en la misma fuente, el valor de width opera siempre como una aproximación y no como un valor absoluto.

La caja de texto puede iniciarse como deshabilitada (el usuario no podrá escribir en ella y aparecerá sombreada) usando el parámetro state.

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

Luego podremos habilitarla nuevamente restableciendo este parámetro vía el método config().

entry.config(state=tk.NORMAL)

Un estado intermedio es "readonly" (solo lectura), en el que el usuario visualiza el control normalmente pero no puede escribir en él.

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

Esto es especialmente útil cuando se quiere prohibir la inserción de texto pero mantener la opción de copiado o los menús contextuales.

Una caja de texto puede recibir el foco cuando si el usuario presiona sucesivamente la tecla Tab, desplazándose por los diversos controles de nuestra interfaz. Si queremos evitar que nuestra caja de texto pueda recibir el foco de esta manera, empleamos el argumento takefocus.

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
root.config(width=300, height=200)
entry = ttk.Entry()
entry.place(x=50, y=50)
# Esta segunda caja de texto no puede recibir el foco
# vía la tecla Tab.
entry2 = ttk.Entry(takefocus=False)
entry2.place(x=50, y=150)
root.mainloop()

Operaciones principales

Ahora bien, una vez creado, las operaciones principales son las siguientes: inserción, obtención, selección y eliminación de texto. Y de éstas, la más frecuente es la segunda, por cuanto nos permite saber qué escribió el usuario de nuestra aplicación. Para las operaciones de copiar, cortar y pegar, véase este artículo.

Empecemos, entonces, por cómo obtener lo que el usuario ha escrito en la caja de texto llamando al método get().

print(entry.get())

Por ejemplo, el siguiente código imprime en la consola el texto ingresado al presionar un botón.

entry.insert(0, "Hola mundo!")
entry.place(x=50, y=50)
button = ttk.Button(text="Obtener texto", command=lambda: print(entry.get()))
button.place(x=50, y=100)

Para añadir un texto empleamos insert(), que toma como primer argumento una posición y como segundo una cadena.

entry.insert(0, "¡Hola, mundo!")

Este código es similar a:

entry.insert(0, "¡Hola,")
entry.insert(6, " mundo!")

Todas las operaciones en Tk que requieran una posición aceptan la constante tk.END, que representa el final del texto. En nuestro caso, tk.END es equivalente a len(entry.get()). Por esto, el siguiente código también consigue el mismo resultado que los dos anteriores.

entry.insert(0, "¡Hola,")
entry.insert(tk.END, " mundo!")

La eliminación de un texto o una parte de él se consigue a través del método delete(), pasándole como argumentos los índices de inicio y fin.

# Elimina el texto completo.
entry.delete(0, tk.END)

De forma análoga opera select_range(), que selecciona el texto desde una posición hasta otra. Por ejemplo, el siguiente código selecciona la palabra «mundo».

entry.insert(0, "¡Hola, mundo!")
# Seleccionar desde el carácter 7 hasta el 12.
entry.select_range(7, 12)
# Enviar el foco a la caja de texto para hacer efectiva
# la selección.
entry.focus()

Para obtener la posición del cursor en la caja de texto, llamamos al método index() con la constante tk.INSERT.

print(entry.index(tk.INSERT))

Y para establecer la posición:

entry.insert(0, "¡Hola, mundo!")
# Ubica el cursor antes de la "m".
entry.icursor(7)
# Envía el foco.
entry.focus()

Tk no provee una función específica para retornar el texto seleccionado, pero haciendo uso del método index() junto con las constantes tk.SEL_FIRST y tk.SEL_LAST ─que retornan los índices de inicio y fin de la selección─ podemos construirla manualmente.

entry.insert(0, "¡Hola, mundo!")

def get_selection():
    # Comprobar primero que haya una selección.
    if entry.select_present():
        # Obtener los índices del inicio y fin de la selección
        first = entry.index(tk.SEL_FIRST)
        last = entry.index(tk.SEL_LAST)
        print(entry.get()[first:last])
    else:
        print("No hay selección.")

button = ttk.Button(text="Obtener selección", command=get_selection)

(El método select_present() retorna True o False según haya un texto seleccionado o no).

Asociando una variable

Cuando una caja de texto es simplemente empleada para recibir un texto ingresado por el usuario, será suficiente con llamar al método get() para obtenerlo cuando sea necesario tal como lo expusimos anteriormente. Pero si nuestro programa requiere cierta funcionalidad bilateral ─se estará tanto insertando texto como obteniendo el ingresado por el usuario─ a menudo es más conveniente asociar una variable.

Tk nos provee la clase tk.StringVar() para crear objetos que actúan como una cadena, con la excepción de que para asignarle un valor usamos el método set() y, para obtenerlo, get().

var = tk.StringVar()
var.set("¡Hola, mundo!")
print(var.get())

Ahora bien, podemos asociar una variable de estas características a una caja de texto al momento de su creación, vía el parámetro textvariable.

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

Así, llamadas a entry_var.set() modificarán el contenido de la caja de texto y, del mismo modo, los cambios efectuados por el usuario en el control afectarán el resultado de entry_var.get().

Validaciones

Tk permite validar el contenido de una caja de texto (por ejemplo, para solo permitir números o fechas) en el momento en que el usuario escribe. Tenemos un artículo aparte para ello: Validar el contenido de una caja de texto en Tcl/Tk (tkinter).

Tipo de letra

Es posible configurar el tipo de letra de una caja de texto vía el parámetro font. Por ejemplo, el siguiente código crea una caja de texto con una tipografía de la familia Times y un tamaño de 14 puntos.

import tkinter as tk
from tkinter import font, ttk

root = tk.Tk()
root.config(width=300, height=200)
entry = ttk.Entry(font=font.Font(family="Times", size=14))
entry.place(x=50, y=50)
root.mainloop()

Caja de texto con fuente personalizada

El argumento font utilizado al crear la caja de texto debe recibir una instancia de la clase tkinter.font.Font. Tk soporta una gran cantidad de familias de fuentes. Para ver una lista completa de los valores posibles del argumento family, ejecútese el siguiente código en la consola interactiva:

>>> import tkinter as tk
>>> root = tk.Tk()
>>> font.families()  # Retorna una lista de las fuentes disponibles.

Otros argumentos aceptables para la configuración de la fuente son weight, slant, overstrike y underline, que indican, respectivamente, el grosor, la inclinación, el tachado y el subrayado:

entry = ttk.Entry(
    font=font.Font(
        family="Courier",
        size=14,
        weight=font.BOLD,   # Negrita.
        slant=font.ITALIC,  # Cursiva.
        overstrike=True,    # Tachado.
        underline=True      # Subrayado.
    )
)

Estilos

El resto de la apariencia de una caja de texto puede configurarse a través de estilos. Para una introducción al funcionamiento de los estilos, véase Apariencia y estilos de los controles en Tcl/Tk (tkinter).

El siguiente código crea un estilo para una caja de texto y establece las propiedades foreground y fieldbackground, que representan el color del texto y el color de fondo, respectivamente.

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
root.config(width=300, height=200)
style = ttk.Style()
style.configure(
    "MyEntry.TEntry",
    # Fondo rojo.
    fieldbackground="#ff0000",
    # Color de texto azul.
    foreground="#0000ff"
)
entry = ttk.Entry(style="MyEntry.TEntry")
entry.place(x=50, y=50)
root.mainloop()

Todos los colores se indican usando la notación RGB en formato hexadecimal o HTML.

Nótese que ciertos sistemas operativos (especialmente Windows) ignoran la propiedad fieldbackground, volviendo imposible la personalización del color de fondo de la caja de texto vía este método. He aquí cómo se ve el mismo código en Ubuntu y Windows:

Caja de texto con texto azul y fondo rojo en Ubuntu

Caja de texto con texto azul

También puede configurarse el aspecto del texto seleccionado:

style.configure(
    "MyEntry.TEntry",
    # Color de fondo del texto seleccionado.
    selectbackground="#87F6F9",
    # Color del texto seleccionado.
    selectforeground="#ff0000",
    # Grosor del borde del texto seleccionado.
    selectborderwidth=2
)

Caja de texto con selección

Así como el color y el grosor del cursor o índice (aquel que indica en qué parte del texto se encuentra el foco):

style.configure(
    "MyEntry.TEntry",
    # Color del cursor o índice.
    insertcolor="#FF46FF",
    # Ancho en píxeles del cursor o índice.
    insertwidth=3
)

Caja de texto con índice personalizado

Por último, se puede alterar el espacio en píxeles que debe haber entre el texto y los márgenes de la caja vía el argumento padding:

style.configure(
    "MyEntry.TEntry",
    # Espacio entre los márgenes de la caja de texto
    # y el texto (en píxeles).
    padding=10
)

Caja de texto con espaciado

Estilos en el control clásico

Las aplicaciones nuevas deberían usar siempre la clase ttk.Entry. Pero si estás actualizando un antiguo código de Tk que aún utiliza el control clásico tk.Entry, al no soportar estilos deberás configurar el aspecto a través de argumentos en el momento en que se crea la caja de texto.

Para los colores del texto y del fondo, utilícense los argumentos foreground y background, respectivamente:

import tkinter as tk

root = tk.Tk()
root.config(width=300, height=200)
# Nótese tk.Entry en lugar de ttk.Entry.
entry = tk.Entry(
    # Color del fondo.
    background="#ff0000",
    # Color del texto.
    foreground="#0000ff",
)
entry.place(x=50, y=50)
root.mainloop()

Para configurar el aspecto del cursor o índice y del texto seleccionado (color y grosor de la selección) se utilizan los mismos argumentos que en los estilos:

entry = tk.Entry(
    # Color del cursor o índice.
    insertbackground="#00ffff",
    # Ancho en píxeles del cursor o índice.
    insertwidth=3,
    # Color de fondo del texto seleccionado.
    selectbackground="#87F6F9",
    # Color del texto seleccionado.
    selectforeground="#ff0000",
    # Grosor del borde del texto seleccionado.
    selectborderwidth=2
)

En el control clásico es además posible configurar el color y grosor del borde de la caja de texto.

entry = tk.Entry(
    # Color del borde cuando tiene el foco.
    highlightcolor="#008000",
    # Color del borde.
    highlightbackground="#ff0000",
    # Grosor del borde.
    highlightthickness=3,
)

El argumento highlightbackground indica el color del borde de la caja cuando el foco está ausente, mientras que highlightcolor indica el color cuando el control tiene el foco.



24 comentarios.

    • Recursos Python says:

      Hola. Podrías hacerlo así:

      CONSTANTE = entry.get()

      Si la constante está definida en un ámbito global vas a tener que usar global para poder cambiar el valor. Pero es un poco contradictorio porque se supone que las constantes son objetos cuyo contenido no cambia.

      Saludos

    • Recursos Python says:

      Hola. Mínimamente necesitarías cajas de texto (Entry) para el asunto y la dirección de correo electrónico, una caja para el mensaje (tk.Text, que soporta múltiples líneas) y un botón (Button) para enviar.

      Saludos

  1. Utilizado este codigo

    Marco2= tk.Entry(ventana,font=('Helvetica',20,'bold'), width= 25, bg="#004445",fg= "white", justify="right")
    Marco2.pack(side=tk.LEFT, padx=200)
    cajatext=tk.Text(ventana, height=15, width= 30)
    cajatext.place(x=900,y=90)
    Marco2.insert(tk.END, cantCaracteres)
    Marco2.insert(0, '\n Cantidad de caracteres: \n')
    Marco2.insert(2, CantCuartillas(cuartilla))
    print (Marco2.get())
    Marco2.place(x=850, y=65, height=650)

    Como puedo hacer para que funciones los saltos de linea del texto mostrado

    • Recursos Python says:

      Hola. Con los controles tk.Entry o ttk.Entry no se puede mostrar un texto de más de una línea. Para eso hay que usar tk.Text.

      Saludos

  2. Hola, necesito que en la casilla de entrada el usuario ingrese su edad y luego comprobar si es mayor de edad,
    ¿Cómo hago para que el valor ingresado lo tome como un entero y no como una cadena?
    Muchas gracias

  3. Una pregunta como hago para que el campo entry los numeros funcionen con los separadores de millares, ya hice la vadilacion ara que solo aceptara numero

  4. Muchas gracias! Por fin encontré un programa que validara una textBox con Entry y lo visualizara en la consola.Muchos programas que publican tienen errores yo se pude hacer nada con ellos cuando se esta empezando cn este lenguaje.

  5. Carles Garrigues says:

    Magnífico. Creo que sois los únicos en internet que explicáis lo del set() get() de Python, EN ESPAÑOL.
    ¡Bravo!

  6. import tkinter as tk
    from tkinter import ttk
    root = tk.Tk()
    root.config(width=300, height=200)
    # Crear caja de texto.
    entry = ttk.Entry(root)
    # Posicionarla en la ventana.
    entry.place(x=50, y=50)
    root.mainloop()

    asi se puede acer tambine

Deja una respuesta