Mostrando entradas con la etiqueta TextBox. Mostrar todas las entradas
Mostrando entradas con la etiqueta TextBox. Mostrar todas las entradas

jueves, 21 de julio de 2022

Curso Guizero 5. Controlando la GUI.


foto de entrada








Anteriormente. 4.- Cambiando el Tamaño de los Widgets y su Orientación.


Vamos a explicar como funciona el código del capítulo anterior en el que diseñamos un procesador de texto sencillo. En muchos editores de texto los usuarios tienen la posibilidad de personalizar el texto, cambiar el tamaño, color, tipo de letra etc. Si intentaste diseñar la aplicación propuesta en el capitulo anterior, seguro que tuviste buenas ideas sobre que controles te gustaría añadir y donde encajarían estos en los widgets respectivos.

Vamos a añadir un ComboBox a nuestro editor de texto que permitirá a los usuarios elegir entre diferentes tipos de letra y también añadiremos un control deslizante para modificar el tamaño del texto. 


desarrollo de la aplicación



Cambiando la fuente del Texto.


Para añadir la posibilidad de cambiar la fuente del texto, necesitamos utilizar un widget ComboBox que permita a los usuarios el elegir entre una lista de fuentes. Para colocarlo, lo situaremos en una caja que estará en la parte inferior del texto. Lo llamaré barra_control ya que será una barra situada en la parte inferior, donde estarán los controles de tipo de letra, tamaño y otros que se aplicarán al texto.

### Remplaza la línea de importación original por esta:
from guizero import App, TextBox, PushButton, Box, Combo, Slider

barra_control = Box(app, align="bottom", width="fill", border=True)
tipo_letra = Combo(barra_control, options=["courier", "times new roman", "verdana"], align="left", command=cambiar_fuente)

Este ComboBox permite a los usuarios escoger entre tres fuentes. Cuando se hace una selección se llamará a la función cambiar_fuente para cambiar la fuente de texto a la que hayamos seleccionado. Para hacer esto tenemos que poner el parámetro command=cambiar_fuente
def cambiar_fuente():
    escritorio.font = tipo_letra.value
Esta función establece la propiedad fuente (font)  del escritorio (TextBox) con el valor seleccionado en el Combo tipo_letra, es decir cambia la fuente elegida.


Cambiando el tamaño del texto.


Para que los usuarios puedan cambiar el tamaño del texto, he agregado una nueva función representada a través de un control deslizante.

Al crear el control deslizante, tendremos que establecer unos parámetros iniciales. Debe estar alojado en la caja barra_control, y alineado de forma que aparezca en la parte inferior y al lado del Combo para cambiar el tipo de letra. También tenemos que indicarle que al modificarse la barra deslizante se llame a la función para cambiar el tamaño de la fuente. La llamaremos cambiar_tamano_texto. Intenta averiguar como funciona.

tamano = Slider(barra_control,  align="left", command=cambiar_tamano_texto, start=10, end=18)
def cambiar_tamano_texto():
    escritorio.text_size = tamano.value
    # Hay que cambiar el tamaño del texto porque si el texto se hace más grande esto podría afectar
    # al tamaño del cuadro de texto , ya que GUIZERO necesita saber como mantener el diseño previsto.
    escritorio.resize(1, 1)
    escritorio.resize("fill", "fill")

Esta función establece la propiedad del cuadro de texto del escritorio en función del valor establecido en el control deslizante. También cambia el tamaño del escritorio para que pueda mostrar el texto, incluso si el texto es muy grande, sin cambiar el diseño de la aplicación. 

A continuación vamos a ver como queda todo el código junto. El tuyo puede ser un poco diferente en función de como sea tu diseño.

from guizero import App, TextBox, PushButton, Box, Combo, Slider

# función para leer archivos:
def push_leer():
    with open(nombreArchivo.value, "r") as f:
        escritorio.value = f.read()
        
# función para escribir archivos:
def push_grabar():
    with open(nombreArchivo.value, "w") as f:
        f.write(escritorio.value)
        
def cambiar_fuente():
    escritorio.font = tipo_letra.value
    
def cambiar_tamano_texto():
    escritorio.text_size = tamano.value
    escritorio.resize(1, 1)
    escritorio.resize("fill", "fill")
    # Hay que cambiar el tamaño del texto porque si el texto se hace más grande esto podría afectar
    # al tamaño del cuadro de texto , ya que GUIZERO necesita saber como mantener el diseño previsto.

app = App(title="Procesador de Textos")

# Crea una caja para meter los controles.
# Queremos que ocupe todo el ancho de la aplicación.
caja = Box(app, align="top", width="fill")

# create a TextBox for the file name
nombreArchivo = TextBox(caja, text="archivo.txt", width=38, align="left")

# create a save button which uses the save_file function
btn_save = PushButton(caja, text="Grabar",  align="right", command=push_grabar)

# create an open button which uses the open_file function
btn_read = PushButton(caja, text="Leer",  align="right", command=push_leer)

# create a TextBox which is not in the box and fills the rest of the GUI
escritorio = TextBox(app, multiline=True, height="fill", width="fill")

barra_control = Box(app, align="bottom", width="fill", border=True)
tipo_letra = Combo(barra_control, options=["courier", "times new roman", "verdana"], align="left", command=cambiar_fuente)

tamano = Slider(barra_control, align="left",
                command=cambiar_tamano_texto, start=10, end=18)

app.display()


Habilitar, Deshabilitar y Ocultar Widgets.

Cuando creamos nuevas funciones, no necesariamente queremos que estén disponibles todo el tiempo. Vamos a ver como habilitarlas o deshabilitarlas según nuestras necesidades.

Muchos editores de texto permiten a los usuarios realizar un seguimiento de si se ha  guardado un archivo desactivando el botón Guardar, cuando el archivo se ha guardado y volviéndolo a activar cuando se realizan nuevas ediciones. Cuando el botón Guardar está deshabilitado, puede aparecer más oscuro o como que está presionado para indicar claramente que no se puede usar.

Vamos a implantar esto mismo en nuestro procesador de texto, de manera que si hemos guardado las modificaciones no podamos pulsar el botón guardar hasta que no haya nuevos cambios.


Habilitando un Widget.


Por cada widget que coloquemos en un Gui, podemos elegir si habilitarlo o no.  Si está habilitado podrá ejecutar su función. Si está deshabilitado, seguirá siendo visible y aparecerá en la aplicación, pero no será interactivo.  Los widgets deshabilitados tienen una apariencia diferente para indicar claramente su estado. 

Podemos configurar un widget para que este habilitado o deshabilitado cuando se crea configurando sus parámetros iniciales. De forma predeterminada están configurados para estar habilitados por defecto.  El siguiente código muestra la diferencia entre un Pushbutton habilitado o deshabilitado.

from guizero import App, PushButton

app = App()

on = PushButton(app, text="on", enabled = True)
off = PushButton(app, text="off", enabled = False)

app.display() 

boton activado y desactivado


También puedes llamar a .enable() y .disable() como métodos en un widget. Esto cambiará el estado del widget a activo o inactivo. Por ejemplo puedes deshabilitar un cuadro de texto como este:

from guizero import App, TextBox

app = App()

textbox = TextBox(app)

textbox.disable()

app.display()

Puedes probar a editar el código y establecer textbox.enable() para ver la diferencia.


Añadiendo Funciones al botón Guardar.

Vamos a aplicar lo que hemos visto anteriormente para crear un botón Guardar que se desactive cuando se ha usado y se vuelva a activar al editar el texto. Lo primero que tenemos que hacer es decirle al PuhButton btn_save que se deshabilite cuando se presiona.  Vamos a añadir el código a la función push_grabar() que es la que guarda el archivo de texto cuando se presiona el botón. El código añadido será el que desactive el botón. Antes de mirar el código, intenta averiguar si sabes cual debería ser esa línea.

# función para escribir archivos:
def push_grabar():
    with open(nombreArchivo.value, "w") as f:
        f.write(escritorio.value)
# Desactiva el botón
    btn_save.disable()
A continuación lo que queremos es que se vuelva a activar cuando se edite el texto. Para hacer esto necesitamos crear una función que lo vuelva a habilitar. Esta función se puede agrupar a las demás al principio del programa. Lo llamaremos enable_btn_save.

def enable_btn_save():
	btn_save.enable()
Queremos que se llame a esta función cuando se edite el texto. El parámetro command en un cuadro de texto llamará a la función cuando se edite el texto, por lo que tendremos que añadir este parámetro en el widget escritorio para conseguir lo que queremos.

escritorio = TextBox(app, multiline=True, height="fill", width="fill", command=enable_btn_save)

Si ahora ejecutamos el código de la aplicación del procesador de textos, deberíamos poder deshabilitar el botón de guardar haciendo clic en él y volver a habilitarlo al editar el texto.

También puedes intentar cambiar el código para que el botón de guardar este deshabilitado al iniciar el programa. 



Hacer que los widgets sean invisibles. 


Una alternativa a deshabilitar los widgets es ocultarlos. Al igual que vimos anteriormente, el ocultar un widget se puede hacer desde sus parámetros iniciales o llamándolos desde un método.

El parámetro inicial por defecto es que el widget este visible. (True por defecto, aunque también se puede configurar como False.) y los métodos a aplicar pueden ser .hide() para hacer el widget invisible y oculto o .show() para hacer visible el widget. 

A veces, puede ser preferible que un widget desaparezca por completo cuando no se puede usar. Sin embargo, cuando un widget se configura como invisible, desaparece por completo y también se elimina del administrador de diseño, por lo que hacer que un widget sea invisible puede afectar la apariencia de su GUI.


Añadiendo una barra de menús.

En lugar de mostrar todas sus funciones directamente, muchos editores de texto tienen una barra de menú que oculta las opciones al usuario hasta que las necesita. Esta es una característica especialmente útil si tienen muchas opciones. En este paso, veremos cómo agregar una barra de menú.

MenuBar

Las barras de menú son widgets en Guizero que te permiten instalar un menú de elementos, cada uno de los cuales puede revelar un submenú desplegable con más opciones.

Menú de Opciones


Una barra de menús debe estar contenida en la aplicación principal. No se puede colocar dentro de un cuadro o cualquier otro tipo de ventana. Para crear uno debemos establecer una lista de nivel superior que describa las opciones que estarán visibles en la aplicación y el contenido de cada submenú, así como las funciones que lo acompañan.

Vamos a verlo con un ejemplo.


from guizero import App, MenuBar

# Estas son las funciones que se llaman seleccionando opciones de cada submenú
def file_function():
    print("Opciones de Archivo")

def edit_function():
    print("Opciones de Edición")

app = App()

menubar = MenuBar(app,
                  # Este es el menú de opciones
                  toplevel=["Archivo", "Editar"],
                  # Las opciones están guardadas en listas anidadas, una lista por cada opción del menú.
                  # Cada opción de la lista contiene un nombre y una función.
                  options=[
                      [ ["Archivo opcion 1", file_function], ["Archivo opcion 2", file_function] ],
                      [ ["Editar opcion 1", edit_function], ["Editar opcion 2", edit_function] ]
                  ])
app.display()

Como podemos ver en este código, las opciones en la barra de menús se registran en una serie de listas.

Hay tres capas de listas:

  • La lista más externa es una lista que contiene todos los submenús. La longitud de esta lista debe ser la misma que la longitud de la lista del nivel superior (toplevel)
  • En la siguiente capa hay una lista para cada submenú.  La longitud de cada una de estas listas debe ser igual a la longitud del submenú correspondiente.
  • La capa más interna es una lista para cada opción de submenú. Cada una de estas listas contiene dos elementos: el nombre de la opción y la función que se llamará cuando se seleccione.

Antes de diseñar una barra de menú para nuestro editor de texto, haz una pausa y piensa qué opciones se deben incluir. Puedes usar el script anterior para que se incluya un nombre para cada opción.


Agregando la Bara de menú al editor de texto. 


Ahora ya lo tenemos todo listo para para agregar una barra de menús al nuestra aplicación de Editor de Texto.

menu de archivo con submenu


Como debe ir en la parte superior de nuestra aplicación y no se puede alojar en una caja, debe ser el primer widget que añadamos. No olvides importar el módulo Menubar.

La barra de menú del siguiente código tiene opciones para abrir un archivo, guardar un archivo y salir del editor.

from guizero import App, TextBox, PushButton, Box, Combo, Slider, MenuBar

# función para leer archivos:
def push_leer():
    with open(nombreArchivo.value, "r") as f:
        escritorio.value = f.read()
        
# función para escribir archivos:
def push_grabar():
    with open(nombreArchivo.value, "w") as f:
        f.write(escritorio.value)
    # Desactiva el botón
    btn_save.disable()
        
def cambiar_fuente():
    escritorio.font = tipo_letra.value
    
def cambiar_tamano_texto():
    escritorio.text_size = tamano.value
    escritorio.resize(1, 1)
    escritorio.resize("fill", "fill")
    # Hay que cambiar el tamaño del texto porque si el texto se hace más grande esto podría afectar
    # al tamaño del cuadro de texto , ya que GUIZERO necesita saber como mantener el diseño previsto.

def enable_btn_save():
    btn_save.enable()
    
# Una nueva función para cerrar la aplicación.
def exit_app():
    app.destroy()


app = App(title="Procesador de Textos")

menubar = MenuBar(app,
                  # Este es el menú de opciones
                  toplevel=["Archivo"],
                  # Las opciones están guardadas en listas anidadas, una lista por cada opción del menú.
                  # Cada opción de la lista contiene un nombre y una función.
                  options=[
                      [ ["Abrir", push_leer], ["Guardar", push_grabar], ["Salir", exit_app]],
                          ])

# Crea una caja para meter los controles.
# Queremos que ocupe todo el ancho de la aplicación.
caja = Box(app, align="top", width="fill")

# create a TextBox for the file name
nombreArchivo = TextBox(caja, text="archivo.txt", width=38, align="left")

# create a save button which uses the save_file function
btn_save = PushButton(caja, text="Grabar",  align="right", command=push_grabar)

# create an open button which uses the open_file function
btn_read = PushButton(caja, text="Leer",  align="right", command=push_leer)

# create a TextBox which is not in the box and fills the rest of the GUI
escritorio = TextBox(app, multiline=True, height="fill", width="fill", command=enable_btn_save)

barra_control = Box(app, align="bottom", width="fill", border=True)
tipo_letra = Combo(barra_control, options=["courier", "times new roman", "verdana"], align="left", command=cambiar_fuente)

tamano = Slider(barra_control, align="left",
                command=cambiar_tamano_texto, start=10, end=18)

app.display()

DESAFIO.

  • En este paso, aprendimos a crear una barra de menús y añadimos un menú con varios submenús. ¿Puedes intentar agregar un segundo submenú a tu barra de menú? (Por ejemplo que tenga la opción de Ayuda y dentro un submenú con el típico "acerca de")
  • ¿ Como se pondría una ventana de advertencia para avisar al usuario si intenta salir de la aplicación sin guardar su archivo ? 
  • ¿Podrías poner un botón para cambiar el editor a "Tema Oscuro" es decir que convierta el fondo a negro y el texto a blanco cuando se pulse.
Si te atascas en el desafío, intenta leer la documentación de Guizero para obtener ayuda. 

Si lo que quieres ver el código del "procesador de textos" terminado, lo puedes encontrar en el siguiente enlace. 


miércoles, 15 de junio de 2022

Curso Guizero 2.- Widgets y Eventos.



Anteriormente. Capítulo 1: Creando una interfaz gráfica de usuario.


Curso de Guizero 2.- Widgets y Eventos.

 Widgets

Ahora que hemos creado nuestra primera y sencilla aplicación GUI usando el widget Text, vamos a ver unos cuantos más que podamos usar.

¿Qué es un Widget?

La palabra "widget" hace referencia a cualquiera de los diferentes elementos que podemos utilizar para construir una interfaz para nuestra aplicación. Aunque no conozcamos aún sus nombres, reconocerás muchos de ellos ya que constantemente los estas viendo en los diferentes programas informáticos o páginas web que utilices.


Diferentes tipos de widgets


En el ejemplo superior se muestran siete tipos de widgets que podemos usar para construir el GUI. Los vamos a describir abajo, junto a una breve descripción de para que los podemos usar.


nombre en guizero nombre en tkinter  descripción
PushButton Button, command button Un botón que se puede pulsar y que sirve para múltiples propósitos. Junto con los cuadros y las etiquetas de texto son de los elementos más utilizados.
TextBox Entry Es una caja en la que se puede ingresar texto. Lo habrás utilizado en cualquier formulario de una página web para ingresar texto, por ejemplo.
Text Labels Las etiquetas de texto se utilizan para mostrar información al usuario. A diferencia de las cajas de texto, el texto no se puede editar.
ButtonGroup Radio button Se utilizan para escoger una opción entre un grupo de ellas. Por ejemplo en una página web se puede utilizar para escoger el pago de un bien con "tarjeta", "efectivo" o "transferencia para el pago". Es posible tener una opción preseleccionada por defecto.
CheckBox Checkbox Una sola casilla que se puede seleccionar y cuyo resultado será True, o False si no está marcada. En el ejemplo superior la opción de escojer entre algunos extras, utilizan el widget checkbox
ComboBox Combobox, drop-down menu Es como un cuadro de texto pero con un menú desplegable que permite al usuario elegir entre varias opciones.
Slider Es un widget que permite escoger un valor usando un control deslizandose a lo largo de una línea.

En este punto, ya hemos visto una descripción de los principales widgets que se pueden usar en una aplicación. También existen otros que se pueden utilizar como barras de menús o imágenes cuya documentación puedes consultar para tener una idea de lo que pueden hacer.


Eventos.


Explicación de los eventos y propiedades. 


Para dar vida a las aplicaciones basadas en un GUI, tenemos que escribir código para responder a los diferentes eventos que pueden suceder. Cada widget es capaz de "sentir" cosas diferentes que les suceden. Por ejemplo para un "PushButton", esto incluye hacer clic, hacer clic con el botón derecho y pasar el mouse sobre él. Los eventos son pues acciones que se realizan sobre el widget.

Así mismo también vimos un explicación breve de lo que son las propiedades. Las configuramos para el widget TexBox, en el capítulo uno, para controlar su color de fondo, el tamaño del texto o su fuente. Las propiedades también se pueden leer, lo que permite obtener valores del usuario, como el valor elegido en un Slider (control deslizante) o el nombre escrito en un TextBox (cuadro de texto).

Leer un valor de una propiedad de un widget es muy sencillo. Si por ejemplo tenemos un TextBox (cuadro de texto) llamado color_favorito en el que el usuario ha escrito la palabra "rosa" podemos guardar este valor en una variable de la siguiente forma usando una variable:

color = color_favorito.value

Para poder experimentar con los eventos y las propiedades, crea un nuevo programa en Python, guárdalo como "eventguide.py" y escribe el siguiente código:

# Importa los widgets que usaremos y creamos la aplicación de nuestro programa.
from guizero import App, TextBox, PushButton, Text, info
app = App()

# La definición de las funciones para los diferentes eventos van aquí.
def btn_go_clicked():
    info("Saludos","Hola, " + txt_name.value + " - Espero que tengas un buen día.")

# Los widgets de tu GUI van aquí.
lbl_name = Text(app, text="Hola. ¿Cómo te llamas?")
txt_name = TextBox(app)
btn_go = PushButton(app, command=btn_go_clicked, text="Hecho")

# Muestra la GUI en la pantalla.
app.display()

Lee el código e intenta imaginar lo que hace.

Ahora ejecuta el código, introduce tu nombre y haz clic en el botón que pone "Hecho".  ¿Hizo el programa lo que te habías imaginado que haría?

El programa, crea tres widgets:

- Una etiqueta de texto con el mensaje "Hola. ¿Cómo te llamas?"

- Un cuadro de texto donde podemos ingresar el nombre.

- Un botón con la etiqueta "Hecho" en el que se puede hacer clic.

aplicación Guizero

Cuando se hace clic en el botón "Hecho", se crea un evento y hay tres líneas de código que manejan el mismo. 

def btn_go_clicked() en la cual se describe que hacer si se pulsa el botón.

info("Saludos", "Hola, " + txt_name.value + " - Espero que tengas un buen día.") 

El código para mostrar una ventana de información cuando se ha pulsado el botón:

  • El primer parámetro "Saludos", es el título de la ventana.
  • El segundo parámetro es el texto que aparecerá dentro de la ventana de información. En este caso un texto de bienvenida que incluye el valor que haya en el cuadro de texto (txt_name.value)
btn_go = PushButton(app, command=btn_go_clicked, text="Hecho")

Cuando el widget PushButton se crea, incluimos command=btn_go_clicked para decirle a este botón, que cuando se pulse, la función btn_go_clicked debería ser ejecutada.

Cuando se ejecuta el programa, Python dibuja la GUI y luego espera a que se active un evento. Tan pronto como se hace clic en el botón (PushButton) se ejecuta el código en la función btn_go_clicked().

Nota. Al codificar una GUI es muy fácil confundirse entre variables, funciones y widgets. Para mejorar la legibilidad, el código incluye etiquetas como txt(texto), lbl (etiqueta) y btn (botón) para que los diferentes elementos que utilizamos puedan identificarse fácilmente.

Cuando escribas tu código, puedes llamar a tus variables y widgets como desees pero es mejor que uses una notación como la anteriormente indicada para que el código sea más fácil de depurar y corregir.

Un Desafio.

La mejor forma de aprender a crear GUIs interactivas es crearlas. Prueba a implementar algunos de estos elementos antes de continuar:

- Agrega dos widgets Text y TextBox para pedirle al usuario otra información (por ejemplo, el nombre de un animal). Cuando se haga clic en el PushButton, el cuadro emergente 'Info' debería mostrar esta nueva información (por ejemplo, 'Tu nombre es  MARIA y te gustan  los CACHORROS').

- Agrega un segundo botón (PushButton). Cuando el usuario haga clic en este botón, debería aparecer un mensaje diferente.

 - Crea una nueva aplicación que le pida al usuario que ingrese una contraseña dos veces y luego les diga si la ingresaron de la misma manera las dos veces.

Puedes hacer clic en el enlace para encontrar una posible solución.

Como te habrás dado cuenta, cuando creamos una aplicación basada en eventos, no sucederá nada después de que se cargue el programa hasta que se active un evento. 

Algunos ejemplos de eventos pueden ser:

- when_clicked Este ya lo hemos usado antes en el ejemplo.

- when_left_button_pressed Esto se puede usar junto con el próximo evento que explicaremos para hacer que los botones parezcan cambiar momentáneamente a medida que se hace clic en ellos.

- when_left_button_released Normalmente se usa junto al evento anterior.

- when_mouse_enters Se activa cuando el cursor del mouse ingresa a un widget. También se puede usar para proporcionar señales visuales a un usuario mientras navega por un GUI.

- when_mouse_leaves Se activa cuando el mouse abandona el widget. 

- when_mouse_dragged Se activa cuando se hace clic en con el mouse y se arrastra el widget.

Podemos configurar una función para que sea llamada por un evento asociado a un widget de la siguiente forma:

nombre_del_widget.when_left_button_pressed = nombre_de_la_función

Nota: a diferencia de cuando llamamos a una función dentro de un programa, en este punto debes asegurarte de poner el nombre de la función si los paréntesis de apertura y cierre al final. () Esto es debido a que estamos usando la función como parámetro y no llamándola directamente.

En el siguiente ejemplo, los eventos when_mouse_enters y when_mouse_leaves se usan para resaltar el cuadro de texto cuando el mouse está sobre él configurando su fondo en azul claro.

# Importa los widgets que usaremos y creamos la aplicación de nuestro programa.
from guizero import App, TextBox, PushButton, Text, info
app = App()

# La definición de las funciones para los diferentes eventos van aquí.
def btn_go_clicked():
    info("Saludos","Hola, " + txt_name.value + " - Espero que tengas un buen día.")

def highlight():
    txt_name.bg = "light blue"

def lowlight():
    txt_name.bg = None

# Los widgets de tu GUI van aquí.
lbl_name = Text(app, text="Hola. ¿Cómo te llamas?")
txt_name = TextBox(app)

# Cuando el cursor del ratón entra en el botón.
txt_name.when_mouse_enters = highlight

# cuando el cursor del ratón sale del botón.
txt_name.when_mouse_leaves = lowlight

btn_go = PushButton(app, command=btn_go_clicked, text="Hecho")

# Muestra la GUI en la pantalla.
app.display()




Una lista con todos los eventos disponibles la puedes encontrar en la página dedicada a Eventos en Guizero.

Desafio. 

Si quieres ver una aplicación completa en la que se utilizan todas estas herramientas y varios widget, puedes seguir el enlace a  la aplicación "El generador de nombres de superheroes" donde se utilizan muchos de estos eventos para generar el nombre ficticio de un superhéroe mediante la selección de varios datos y también puedes cambiar toda la aplicación al modo oscuro.

sábado, 19 de marzo de 2022

Lista de widgets en tkinter y guizero.


Imagen introductoria: widgets




Lista de Widgets en Tkinter y Guizero.


En este capítulo vamos a repasar algunos de los elementos más importantes que podemos encontrar en una aplicación Gráfica (GUI) y una descripción sencilla del código para generarlo tanto en Tkinter como en Guizero.

Ejemplos de código para los widgets de tkinter.
Ejemplos de código para los widgets de Guizero.

¿Que es un widget? 


Un widget describe cada una de las diferentes partes que pueden ser usadas para crear una interfaz de usuario o GUI
Aunque no te suenen sus nombre, reconocerás muchos de ellos en los diferentes programas o websites que utilizas.

El siguiente ejemplo muestra siete widgets en Guizero. Aunque sus nombres en Tkinter pueden variar un poco básicamente son los mismos, ya que recuerda que Guizero usa Tkinter para funcionar. 


diferentes widgets


Vamos a ir viéndolos uno a uno junto una pequeña descripción de su uso. Luego haremos un pequeño ejemplo con ambos programas para ver como programarlos. En otros capítulos veremos las diferentes propiedades y métodos que pueden tener cada uno y entraremos más en detalle.

Tipos de Widgets.

_______________________________________________________________________________
 
Nombre en Tkinter Nombre en Guizero
Frame Box

Es un widget que actúa como contenedor para otros widgets. Es invisible por defecto y puede ser usado para colocar más fácilmente otros widgets dentro de la ventana y alterar su diseño. En el ejemplo crearemos una caja (llámale Frame o Box) y colocamos dos botones dentro.

Tkinter
demostración de frame


from tkinter import *
# Creamos la aplicacion principal y su tamaño
raiz = Tk()
raiz.geometry("200x150")

# Creamos una caja alineada a la izquierda que ocupe toda la ventana y con borde
# para que podamos verlo.
frame=Frame(raiz)
frame.config(bg="lightblue")
frame.pack(side="left", fill="x", expand=1)

# Colocamos un boton dentro del Frame
button=Button(frame,text="botón")
button.pack()
# Colocamos otro boton dentro del mismo Frame
button1= Button(frame, text="Otro botón")
button1.pack()

raiz.mainloop()

Guizero

demostración de widget frame


# importamos la ventana principal, una caja y un botón
from guizero import App, Box, PushButton
# Creamos la aplicación principal
app = App(width=200, height=150)

# Creamos una caja alineada a la izquierda que ocupe toda la ventana y con borde
# para que podamos verlo.
box = Box(app, align="left", width="fill", border=2)
# Colocamos un botón
button = PushButton(box)
# Colocamos otro que se pone debajo
button1 = PushButton(box, text="another button")

app.display()
_______________________________________________________

Nombre en TkinterNombre en Guizero
ButtonPushButton

Es un botón que se puede pulsar y que sirve para una multitud de propósitos. Es uno de los que más frecuentemente se utiliza. Una vez que se pulsa lanza alguna acción en el programa. 

Tkinter

widget button en tkinter


from tkinter import *
 
def set():
    print("Hola Mundo")
 
root = Tk()
root.geometry("200x150")
 
frame = Frame(root)
frame.pack()
button = Button(frame, text = "Botón1", command = set,
                fg = "red", font = "Verdana 14 underline",
                bd = 2, bg = "light blue", relief = "groove")
button.pack(pady = 5)
 
root.mainloop()
Guizero

button widget en guizero



# importamos la ventana principal, una caja y un botón
from guizero import App, Box, PushButton

def set():
    print("Hola Mundo")
    
# Creamos la aplicación principal
app = App(width=200, height=150)

# Creamos una caja alineada a la izquierda que ocupe toda la ventana y con borde
# para que podamos verlo.
box = Box(app)
# Colocamos el botón con una serie de propiedades iniciales
button = PushButton(box, text="Botón1", command=set)
# Propiedades adicionales de los botones
button.bg="light blue"
button.text_color="red"
# incluso podemos usar directamente un método de tkinter en guizero
# <nombre>.tk.config()
button.tk.config(bd=2, relief = "groove",font = "Verdana 14 underline")
button.tk.pack(pady=5)
_______________________________________________________

Nombre en TkinterNombre en Guizero
EntryTextBox

Se usa para que el usuario pueda introducir datos desde la aplicación. Es una caja de texto en donde el usuario puede introducir datos.

Tkinter




from tkinter import *
 
root = Tk()
root.geometry("200x150")
 
frame = Frame(root)
frame.pack()
 
my_entry = Entry(frame, width = 20)
my_entry.insert(0,'Username')
my_entry.pack(padx = 5, pady = 5)
 
my_entry2 = Entry(frame, width = 15)
my_entry2.insert(0,'password')
my_entry2.pack(padx = 5, pady = 5)
 
root.mainloop()

Guizero



from guizero import App, TextBox, Box
raiz = App(width=200, height=150)

# no existen paddings para los box en guizero
# para lograr lo mismo hay que usar tkinter o como en
# este caso meter algo por medio.

# Caja de relleno que no se ve pero esta ahí
Box(raiz, align="top", width="fill", height=5)
# Caja Principal que contiene los inputs.
box = Box(raiz)

inputA = TextBox(box, width=20,text="Username")
inputB = TextBox(box, width=15, text="Password")
raiz.display()

_______________________________________________________

Nombre en TkinterNombre en Guizero
Check Button 
CheckBox

Las casillas de verificación permiten al usuario escoger entre un conjunto de acciones que ya están predefinidas. El usuario puede escoger más de una opción.


Tkinter

check button en tkinter


root = Tk()
root.geometry("200x150")
 
frame = Frame(root)
frame.pack()
 
Var1 = IntVar()
Var2 = IntVar()
 
ChkBttn = Checkbutton(frame, width = 15, text="Opción 1", variable = Var1)
ChkBttn.pack(padx = 5, pady = 5)
 
ChkBttn2 = Checkbutton(frame, width = 15, text="Opción2", variable = Var2)
ChkBttn2.pack(padx = 5, pady = 5)

root.mainloop()

Guizero

checkbox en guizero


from guizero import App, CheckBox, Box

# Creamos la aplicación principal
app = App(width=200, height=150)

# Creamos una contenedor
box = Box(app)
# Incorporamos las casillas de verificación.
checkbox_1 = CheckBox(box, text="Opción1")
checkbox_1 = CheckBox(box, text="Opción2")

app.display()

______________________________________________________

Nombre en TkinterNombre en Guizero
Radio Button 
ButtonGroup

Se muestra un conjunto de casillas de verificación redondas, en donde el usuario puede escoger una única opción.

Tkinter

Radio Button en tkinter


from tkinter import *
 
root = Tk()
root.geometry("200x150")
frame = Frame(root)
frame.pack()
 
Var1 = StringVar()
 
RBttn = Radiobutton(frame, text = "Option1", variable = Var1,
                    value = 1)
RBttn.pack(padx = 5, pady = 5)
 
RBttn2 = Radiobutton(frame, text = "Option2", variable = Var1,
                     value = 2)
RBttn2.pack(padx = 5, pady = 5)
 
root.mainloop()

Guizero.

En el ejemplo usamos un ButtonGroup que muestra la selección en una caja de texto.

ButtonGroup en guizero


from guizero import App, ButtonGroup, Text, Box

def update_text():
    seleccionada.value = opciones.value

app = App(width=200, height=150)
opciones = ButtonGroup(app, options=
                              ["Opción 1",
                              "Opción 2"],
                            selected="Opción 1", command=update_text)

caja = Box(app, border=2)
seleccionada = Text(caja, "Opción 1")
app.display()

______________________________________________________

Nombre en TkinterNombre en Guizero
LabelText, Picture

Muestra un texto dentro de la aplicación que el usuario no puede modificar. Es bastante útil para poner títulos, etiquetas o instrucciones. Es muy versátil y lo podemos usar incluso para incluir imágenes.

Tkinter.

Label en tkinter



from tkinter import *
 
root = Tk()
root.geometry("200x150")
 
frame = Frame(root)
frame.pack()
 
var = StringVar()
var.set("Hola Mundo")
 
label = Label(frame, textvariable = var )
label.pack()
 
root.mainloop()

Guizero.

text en guizero


from guizero import App, Text

app = App(width=200, height=150)

texto = Text(app, text="Hola Mundo!")

app.display()
* Usamos el widget Picture si en vez de mostrar un texto queremos que se incluya una imagen.

_____________________________________________________


Nombre en TkinterNombre en Guizero
MenuMenuBar

Este wigdet muestra un menú en la parte superior de la pantalla, y cada opción del menú conduce a un submenú.

Tkinter

Menu en Tkinter


from tkinter import *
 
def save():
    #Código a ser escrito
    pass
 
def load():
    #Código a ser escrito
    pass   
 
root = Tk()
root.geometry("200x150")
frame = Frame(root)
frame.pack()
 
mainmenu = Menu(frame)
mainmenu.add_command(label = "Save", command= save)  
mainmenu.add_command(label = "Load", command= load)
mainmenu.add_command(label = "Exit", command= root.destroy)
 
root.config(menu = mainmenu)
 
root.mainloop()
Guizero.

MenuBar en guizero


from guizero import App, MenuBar
def file_function():
    pass #codigo a rellenar

def edit_function():
    pass #codigo a rellenar
    
def exit_function():
    app.destroy()

app = App(width=200, height=150)
menubar = MenuBar(app,
                  toplevel=["Save", "Load", "Exit"],
                  options=[
                      [ ["Guardar", file_function], ["Guardar como..", file_function] ],
                      [ ["Cargar", edit_function], ["Cargar archivo", edit_function] ],
                      [ ["Salir", exit_function]],
                  ])
app.display()

_______________________________________________________

Nombre en TkinterNombre en Guizero
ComboBoxCombo

Este objeto lo que hace es mostrar un cuadro desplegable que permite seleccionar una sola opción dentro de una lista de opciones.

Tkinter.

Combobox de tkinter



from tkinter import *
from tkinter import ttk
 
root = Tk()
root.geometry("200x150")
 
frame = Frame(root)
frame.pack()
 
vlist = ["Option1", "Option2", "Option3",
          "Option4", "Option5"]
 
Combo = ttk.Combobox(frame, values = vlist)
Combo.set("Escoge una opción")
Combo.pack(padx = 5, pady = 5)
 
root.mainloop()

Guizero.

Combo en guizero


from guizero import App, Combo
app = App(width=200, height=150)
combo = Combo(app, options=["Opción 1", "Opción 2", "Opción 3"])
app.display()

_______________________________________________________

Nombre en TkinterNombre en Guizero
List Box
ListBox

Se utiliza para mostrar una lista de opciones al usuario en donde elegir. Se puede escoger una o varias de ellas.

Tkinter.

List box en tkinter


from tkinter import *
root = Tk()
root.geometry("200x220")
frame = Frame(root)
frame.pack()
 
label = Label(root,text = "Escoge elementos a comprar.")  
label.pack()  
   
listbox = Listbox(root)  
   
listbox.insert(1,"Pan")  
listbox.insert(2, "Leche")  
listbox.insert(3, "Carne")  
listbox.insert(4, "Queso")
listbox.insert(5, "Verduras")  
   
listbox.pack()  
root.mainloop()

Guizero.

ListBox en guizero

from guizero import App, ListBox, Text
app = App(width=200, height=150)
Text(app, text="lista de la compra")
listbox = ListBox(app, items=["Pan", "Leche", "Carne", "Queso"])
app.display()

______________________________________________________

Nombre en TkinterNombre en Guizero
Menu Button-


Es una combinación entre el widget de menú y el de botón. Muestra un menú desplegable con una lista de opciones cuando hacemos click en él. Este widget es único porque puede incorporar aspectos de botones de opción y de opciones de verificación.

Tkinter

Menu Button en tkinter


from tkinter import *
 
root = Tk()
root.geometry("200x150")
frame = Frame(root)
frame.pack()
 
MenuBttn = Menubutton(frame, text = "Favourite food", relief = RAISED)
 
Var1 = IntVar()
Var2 = IntVar()
Var3 = IntVar()
 
Menu1 = Menu(MenuBttn, tearoff = 0)
 
Menu1.add_checkbutton(label = "Pizza", variable = Var1)
Menu1.add_checkbutton(label = "Cheese Burger", variable = Var2)
Menu1.add_checkbutton(label = "Salad", variable = Var3)
 
MenuBttn["menu"] = Menu1
 
MenuBttn.pack()
root.mainloop()

______________________________________________________

Nombre en TkinterNombre en Guizero
CanvasDrawing

Aunque no son exactamente igual en ambas librerías, nos permite dibujar formas, imágenes o texto. Es como una pizarra en la que puedes pintar o dibujar cualquier cosa.

Tkinter.

Canvas en Tkinter


from tkinter import *
 
root = Tk()
 
frame=Frame(root,width=300,height=300)
frame.pack(expand = True, fill=BOTH)
 
canvas = Canvas(frame,bg='white', width = 300,height = 300)
 
coordinates = 20, 50, 210, 230
arc = canvas.create_arc(coordinates, start=0, extent=250, fill="blue")
arc = canvas.create_arc(coordinates, start=250, extent=50, fill="red")
arc = canvas.create_arc(coordinates, start=300, extent=60, fill="yellow")
 
canvas.pack(expand = True, fill = BOTH)
 
root.mainloop()

Guizero.

Drawing in guizero


from guizero import App, Drawing
app = App(width=200, height=150)
drawing = Drawing(app)
drawing.rectangle(10, 10, 60, 60, color="blue")
app.display()
_______________________________________________________


Nombre en TkinterNombre en Guizero
ScalaSlider


Este objeto muestra una barra y un selector que puede usarse para especificar un valor en un rango.

Tkinter.

Scala en tkinter


from tkinter import * 
 
root = Tk()
root.geometry("200x200")
frame = Frame(root)
frame.pack()
 
Scala = Scale(frame, from_=0, to=10)
Scala.pack(padx=5, pady=5)
 
Scala2 = Scale(frame, from_=0, to=10, orient=HORIZONTAL)
Scala2.pack(padx=5, pady=5)
 
root.mainloop()

Guizero.



from guizero import App, Slider
app = App(width=200, height=150)
slider = Slider(app, horizontal=False)
slider = Slider(app)
app.display()
______________________________________________________


Nombre en TkinterNombre en Guizero
ScrollBar-

Este widget nos va a permitir el desplazarnos por un ventana de Tkinter o mejor dicho habilitar el desplazamiento para ciertos widgets. Por lo general se usa cuando tienes un espacio limitado para una ventana en Tkinter pero quieres más espacio para el widget. Veámoslo con un ejemplo.

ScrollBar in tkinker


root.geometry("200x250") 
    
mylabel = Label(root, text ='Scrollbars', font = "30")  
mylabel.pack() 
 
myscroll = Scrollbar(root) 
myscroll.pack(side = RIGHT, fill = Y) 
 
mylist = Listbox(root, yscrollcommand = myscroll.set )  
for line in range(1, 100): 
    mylist.insert(END, "Number " + str(line)) 
mylist.pack(side = LEFT, fill = BOTH )    
 
myscroll.config(command = mylist.yview) 
    
root.mainloop() 

_______________________________________________________

Nombre en TkinterNombre en Guizero
ToplevelWindow

Este widget nos va a permitir nuevas ventanas.

Tkinter.



from tkinter import *
 
def NuevaVentana():
    window = Toplevel()
    window.geometry('150x150')
    newlabel = Label(window, text = "Settings Window")
    newlabel.pack()
 
 
root = Tk()
root.geometry('200x200')
 
myframe = Frame(root)
myframe.pack()
 
mybutton = Button(myframe, text = "Settings", command = NuevaVentana)
mybutton.pack(pady = 10)
 
root.mainloop()

Guizero.

window in guizero


from guizero import App, Window, PushButton

def open_window():
    window.show(wait=True)

app = App(title="My app", height=200, width=200)

window = Window(app, title = "2nd ventana", height=150, width=150)
# La ventana esta creada pero la ocultamos para que no se vea
# hasta que se pulse el botón que la vuelva visible.
window.hide()

open=PushButton(app, text="Segunda ventana", command=open_window)

app.display()

_______________________________________________________

Nombre en TkinterNombre en Guizero
Notebook


Este Widget nos permite seleccionar páginas de contenido haciendo clic en las pestañas.

Tkinter.



Cuando se hace clic en alguna de estas pestañas, el widget Notebook mostrará un panel secundario asociado a la pestaña seleccionada. Normalmente este panel secundario mostrado es un widget Frame de tkinter. 

Para crear este widget, usamos la clase ttk.Notebook de la siguiente forma:

notebook = ttk.Notebook(contenedor, opciones**)
Por lo general el contenedor suele ser la raíz del proyecto.

Este contenedor tiene algunas opciones útiles. Por ejemplo se puede especificar las opciones height and width para especificar el alto y ancho en pixeles asociados al widget.

Además también podemos agregar algo de espacio alrededor del widget usando la opción "padding".


Métodos del Notebook.


La clase ttk.Notebook tiene varios métodos que permiten gestionar las ventanas de una manera efectiva.

Veamos los más utilizados: 

add(child, Kwargs**)

El método add agrega un widget secundario a una ventana. Se le puede pasar una o más opciones.

child es el widget para agregar al Notebook o cuaderno.

La opción "text" especifica la etiqueta que aparecerá en la ventana. 

La opción "image" especifica la imagen que se mostrará en la pestaña.

Si usamos ambas tenemos que describir la posición de la imagen en relación al texto. Puede ser:
tk.TOP , tk.BOTTOM, tk.LEFT, tk.RIGHT o tk.CENTER.

La opción "underline" toma como valores 0 o un número positivo. Esto subraya el caracter que le indiquemos, pero solo uno. Si ponemos underline=0, solo subrayará el primer carácter, si ponemos 1 subrayará el segundo y así sucesivamente.

hide(tabId) 

Este método oculta temporalmente la pestaña identificada por el tabId del Notebook. Como siempre la primera pestaña es la 0, la siguiente la 1 y así sucesivamente.

Para volver a mostrar la ventana hay que volver a utilizar el método add() ya que en este caso no hay un método show()

forget(child)

Elimina permanentemente el widget indicado del Notebook.

El siguiente programa muestra como crear un Notebook con dos pestañas:

import tkinter as tk
from tkinter import ttk

# root window
root = tk.Tk()
root.geometry('400x300')
root.title('Ejemplo de Widget Notebook')

# create a notebook
notebook = ttk.Notebook(root)
notebook.pack(pady=10, expand=True)

# create frames
frame1 = ttk.Frame(notebook, width=400, height=280)
frame2 = ttk.Frame(notebook, width=400, height=280)

frame1.pack(fill='both', expand=True)
frame2.pack(fill='both', expand=True)

# add frames to notebook

notebook.add(frame1, text='Pestaña A', underline=1)
notebook.add(frame2, text='Pestaña B')


root.mainloop()

Guizero.

No existe un elemento especifico para crear un Notebook en guizero asi que tenemos que usar el elemento ttk.Notebook de tkinter.

from guizero import App, Box
from tkinter import ttk
from tkinter.ttk import Notebook

# set up app to use grid layout
app = App(title="Uso de ttk Notebook", layout="grid")

# set up box to use grid and place it in app at 0,0
box = Box(app, border=True, layout='grid', grid=[0,0])

# create a notebook
nb = Notebook(box.tk)

# create some frames for the tabs
pestana_a = ttk.Frame(nb)
pestana_b = ttk.Frame(nb)

# add the tabs
nb.add(pestana_a, text='Pestaña A')
nb.add(pestana_b, text='Pestaña B')

# important - add tk widget only after it is completed
box.add_tk_widget(nb, grid=[0,0])


app.display()
Puedes ver como usar esta forma de utilizar elementos de tk en Guizero en este enlace a la página del manual de Guizero.