Tkinter - INTRODUCCIÓN


Tkinter es una librería que hace uso de Tcl/Tk para el desarrollo de interfaces gráficas de usuario en Python.

Python no dispone de soporte nativo para el desarrollo de interfaces gráficas, pero Tkinter es parte de la biblioteca estándar de Python, es decir, no hay que instalar Tkinter si ya tienes instalado Python.

Tkinter permite utilizar Tcl/Tk desde Python, de modo que aunque internamente se estén ejecutando instrucciones Tcl estaremos desarrollando interfaces gráficas escribiendo unicamente código Python.



PRIMER PROGRAMA CON TKINTER


Vamos a crear nuestro primer programa con Tkinter. Para ello crea un archivo programa.py y escribe el siguiente código:

from tkinter import *       # Importamos el módulo tkinter

root = Tk()                 # root es el widget principal: un objeto de la clase Tk
root.mainloop()             # El médoto .mainloop es el bucle principal de escucha de eventos

Al ejecutar el script programa.py aparece el siguiente formulario:

Primer Programa Tkiner

Has creado tu primer programa con Tkinter pero de momento no hace nada . Lo único que puedes hacer es redimensionar el tamaño del formulario, minimizarlo o maximizarlo, y cerrarlo.

Ten en cuenta que la apariencia del formulario depende del sistema operativo en el que este se está ejecutando, y puede no ser exactamente igual al que te estoy mostrando en la imagen (yo he utilizado Python 3.6 en Windows 7).

Además del formulario observa la consola de comandos. En un programa con interfaz gráfica es deseable que la consola permanezca oculta. Para conseguir esto debes renombrar tu script a programa.pyw, ya que los archivos con extensión .pyw son ejecutados por pythonw.exe en lugar de python.exe).

Sin embargo, durante el desarrollo de un programa es preferible que la consola permanezca visible, ya que si se produce algún error este será notificado por la consola (yo utilizaré la salida por consola para exponer algunos ejemplos).

Dicho esto, analicemos el código escrito hasta ahora:

Las interfaces creadas con Tkinter son un conjunto de widgets que tienen una jerarquía. Un widget padre puede contener un conjunto de widgets hijos. En nuestro programa, root es el widget raíz o principal dentro del cual añadiremos el resto de widgets.

Los widgets pueden responder a una serie de eventos (por ejemplo, un click con el botón izquierdo del ratón sobre un botón). Esto es posible gracias al método Tk.mainloop, que pone en marcha un bucle infinito que comprueba si se ha producido algún evento, y en caso afirmativo ejecuta los manejadores del evento asociados (si es que existen).

De momento nuestro programa no hace nada, ya que no hemos añadido widgets ni hemos definido manejadores de eventos o comandos asociados a botones. Sin embargo, es el método Tk.mainloop el que hace que el programa permanezca abierto hasta pulsar el botón X o hasta cerrar la consola de comandos (si esta se encuentra visible).

Antes de dotar a nuestro programa de auténtica funcionalidad vamos a ver como modificar algunas propiedades de formulario root. Si observas el formulario verás que el título del mismo es 'tk' y que el icono es una pluma. Esta pluma es el logotipo de Tcl.


CAMBIAR EL TÍTULO Y EL ICONO DEL PROGRAMA


from tkinter import *

root = Tk()

root.title('Primer Programa') # Método Tk.title - Asigna el título del programa
root.iconbitmap('icon.ico')   # Método Tk.iconbitmap - Asigna el icono del programa

root.mainloop()

El método Tk.title("title") permite asignar el título del programa.

Con el método Tk.iconbitmap("icon_path") podemos configurar el icono del formulario indicando la dirección absoluta o relativa del mismo. Yo he utilizado este icono, que he copiado en el mismo directorio que programa.py y he indicado su dirección relativa ("icon.ico").

Ahora, al ejecutar el programa el formulario se verá así:

Asignacion de título e icono


AÑADIR UNA ETIQUETA (Label)


Ya tenemos un formulario con un título e icono personalizados . Es hora de añadir algún widget a root. Lo primero que vamos a hacer es añadir una etiqueta (Label) que muestre el texto "Hola Mundo Tkinter". Para ello edita programa.py así:

from tkinter import *

root = Tk()

root.title('Primer Programa')
root.iconbitmap('icon.ico')

etiqueta = Label(root, text='Hola Mundo Tkinter')     # Clase Tk.Label (etiqueta de texto)
etiqueta.pack()                                       # Método Tk.Label.pack

root.mainloop()

Ejecuta el programa y verás lo siguiente:

Hola Mundo Tkinter

En nuestro código, etiqueta es un objeto de la clase Label, que es un tipo de widget utilizado para mostrar texto en el formulario.

En Tkinter, el primer parámetro pasado a las clases que definen los widgets siempre es el widget padre, es decir, aquel en el que queremos meter el widget que estamos creando. Con etiqueta = Label(root, text='Hola Mundo Tkinter') estamos creando un widget del tipo Label que muestra el texto "Hola Mundo Tkinter" y cuyo widget padre es root.

Con etiqueta.pack() ponemos la etiqueta que hemos definido en nuestro formulario, para que sea visible.

Observa que ahora el formulario desplegado es mas pequeño que aquel para el que no habíamos añadido una etiqueta. Esto se debe a que no hemos configurado las dimensiones del formulario, de manera que si este no contiene widgets toma un valor inicial por defecto. Si el formulario contiene widgets y no hemos configurado las dimensiones iniciales, este tomará unicamente el espacio necesario para que todos los widgets que contiene sean visibles.

Fíjate en que aún es posible redimensionar el formulario:

Hola Mundo Tkinter Redimensionado

Al expandir el formulario, la etiqueta queda centrada horizontalmente pero no verticalmente. Si queremos que también se centre verticalmente podemos hacerlo gracias al parámetro expand del método pack del widget:

from tkinter import *

root = Tk()

root.title('Primer Programa')
root.iconbitmap('icon.ico')

etiqueta = Label(root, text='Hola Mundo Tkinter')
etiqueta.pack(expand=True)  # <--- FÍJATE

root.mainloop()

Al ejecutar el programa y expandir el formulario comprobamos como ahora la etiqueta queda centrada, tanto horizontal como verticalmente:

expand para centrar widget en Tkinter

El método pack admite otros parámetros para configurar el posicionamiento de nuestros widgets, pero de momento no vamos a hablar de ellos.


DIMENSIONES Y REDIMENSIÓN


Podemos configurar las dimensiones iniciales de nuestro formulario (root) mediante el método geometry.

Por ejemplo, si queremos que las dimensiones de nuestro formulario sean 240x120 podemos configurar root.geometry('240x120'), quedando nuestro script así:

from tkinter import *

root = Tk()

root.title('Primer Programa')
root.iconbitmap('icon.ico')
root.geometry('240x120')    # <--- FÍJATE

etiqueta = Label(root, text='Hola Mundo Tkinter')
etiqueta.pack(expand=True)

root.mainloop()

Al abrir el programa aparece el formulario con las dimensiones que hemos especificado (240x120), sin embargo todavía podemos expandir y contraer el formulario, es decir, podemos redimensionarlo.

Podemos deshabilitar la redimensión del formulario mediante el método resizable(x, y). Si queremos deshabilitar la redimensión tanto en el eje X como en el eje Y de manera que las dimensiones del formulario no puedan modificarse durante la ejecución del programa haríamos lo siguiente:

from tkinter import *

root = Tk()

root.title('Primer Programa')
root.iconbitmap('icon.ico')
root.geometry('240x120')
root.resizable(False, False)    # <--- FÍJATE

etiqueta = Label(root, text='Hola Mundo Tkinter')
etiqueta.pack(expand=True)

root.mainloop()

Por defecto sí se puede redimensionar el formulario porque si no se especifica otra cosa: root.resizable(True, True)

Hasta aquí hemos visto como configurar algunas propiedades importantes del formulario. Para finalizar vamos a sustituir nuestra etiqueta (Label) por un botón (Button) y conseguir así que nuestro programa haga algo.


AÑADIR UN BOTÓN Y DARLE FUNCIONALIDAD


Edita programa.py del siguiente modo:

from tkinter import *

root = Tk()

root.title('Primer Programa')
root.iconbitmap('icon.ico')
root.geometry('240x120')
root.resizable(False, False)

boton = Button(root, text='Saludar')  # He sustituido etiqueta = Label por boton = Button
boton.pack(expand=True)

root.mainloop()

He sustuido Label por Button, es decir, ahora nuestro widget es un botón. El identificador etiqueta lo he sustituido por boton por coherencia, pero esto no era estrictamente necesario. También he sustituido el texto del widget por 'Saludar'.

Pues bien, si ahora ejecutas el programa comprobarás que aparece un formulario con un botón en el que figura el texto 'Saludar'.

Formulario Tkinter con botón

Si haces click en el botón no sucede nada, pero es muy fácil hacer que el botón responda al click mediante el parámetro command, que indica la función que debe ejecutarse cuando se hace click sobre el botón.

Observa el siguiente ejemplo:

from tkinter import *


# Definimos la función saludar, que asignaremos como comando del botón
def saludar():
    print('Hola Mundo Tkinter')



root = Tk()

root.title('Primer Programa')
root.iconbitmap('icon.ico')
root.geometry('240x120')
root.resizable(False, False)

boton = Button(root, text='Saludar', command=saludar) # Asignamos la función saludar como comando del botón
boton.pack(expand=True)

root.mainloop()

Si ahora ejecutas el programa, cada vez que hagas click en el botón se ejecutará la función saludar, que imprimirá el texto 'Hola Mundo Tkinter' en la consola. En la siguiente imagen he hecho click tres veces sobre el botón:

Tkinter - Ejemplo imprimir en consola

Ya tienes un programa que realmente hace algo, aunque lo que hace no sea espectaculas (de momento jeje). Como la función saludar es muy sencilla (solamente ejecuta una intrucción) podríamos simplificar el programa utilizando una función lambda, de la siguiente manera:

from tkinter import *


root = Tk()

root.title('Primer Programa')
root.iconbitmap('icon.ico')
root.geometry('240x120')
root.resizable(False, False)

boton = Button(root, text='Saludar', command=lambda:print('Hola Mundo Tkinter')) # <--- FÍJATE
boton.pack(expand=True)

root.mainloop()

Con esto damos por finalizada esta breve introducción a Tkinter.



RESUMEN


En este capítulo hemos visto como crear un sencillo programa de un solo formulario. Hemos visto como configurar algunas de sus propiedades (título, icono, dimensiones y si es o no redimensionable).

Mencionamos como ocultar la consola de comandos (.pyw), aunque por el momento es preferible dejarla visible para ver los ejemplos.

Hemos mencionado lo que son los widgets y hemos echado un vistazo a dos de ellos: Label y Button.

Finalmente hemos visto como dar funcionalidad a un botón. Concretamente hemos hecho que al hacer click sobre un botón se ejecute una determinada función.



ANOTACIONES


En Kubuntu 18.04 y Python3.6, al intentar asignar root.iconbitmap('icon.ico') se produce un error.

La única solución que he encontrado ha sido utilizar archivos .png y sobreescribir el método root.iconbitmap del siguiente modo:

root.iconbitmap = lambda icon_path: root.tk.call('wm', 'iconphoto', root._w, PhotoImage(file=icon_path))
root.iconbitmap('icon.png')


¡Continúa aprendiendo! - Cuadros de Diálogo y Mensajes en Tkinter