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. 


lunes, 4 de julio de 2022

Curso Guizero 4. Cambiando el Tamaño de los widgets y su Alineación.

aplicación procesador de texto



Curso Guizero 4. Cambiando el tamaño de los Widgets y su Alineación.

Un elemento importante a considerar a la hora de planificar una GUI es el tamaño de los elementos que la componen. En este capitulo, vamos a ver diferentes métodos para cambiar tanto la altura como el ancho de los widgets.

LOS GESTORES DE VENTANAS.

Antes de ponernos a cambiar el tamaño y diseño de los widgets de nuestra aplicación, es importante que tengamos en cuenta el papel que desempeña el administrador de ventanas, que es una parte del sistema operativo con el que estemos trabajando. 

El administrador de ventanas es el que finalmente establece como se van a ver nuestros widgets, donde se colocan en la ventana y que propiedades se pueden cambiar. 

Por ejemplo, el mismo código ejecutado en diferentes sistemas operativos da lugar a resultados diferentes:

el mismo widget en diferentes sistemas operativos.

De izquierda a derecha: macOS, windows10 y Rapsbian.

Aunque las diferencias entre ambos son pequeñas, no debes pensar que tu código dará lugar a los mismos resultados en diferentes sistemas operativos.


Parámetros de tamaño.

Los parámetros height (alto) y width (ancho) nos permiten cambiar fácilmente las dimensiones de los widgets.

Para especificar el alto y ancho de un widget podemos usar estos parámetros al crear el widget. Si no lo hacemos este se creará con un tamaño predeterminado. Pero también podemos especificarlos después de haberlos creado para cambiar su tamaño.

Si ejecutas el siguiente código puedes ver un ejemplo de un widget PushButton configurado con el tamaño predeterminado y otro con 10 caracteres de alto y 20 de ancho:


from guizero import App, PushButton
app = App()
button = PushButton(app, text="Tamaño por Defecto")
button_sized = PushButton(app, text="Nuevo tamaño", width=20, height=10)
app.display()

diferentes tamaños para los widgets.


Para algunos widgets la altura y anchura se miden en caracteres, es decir la cantidad de letras y símbolos que caben en el espacio. Para otros la altura y anchura se miden en pixeles. Es importante saber que widgets utilizan que medidas, ya que los caracteres no tienen el mismo tamaño que los pixeles.

En Guizero, los widgets Box, ListBox, Picture, Slider y Waffle se miden en píxeles, al igual que un PushButton que contiene una imagen.


Filling

Una forma alternativa para especificar el alto y el ancho de un widget es configurar sus parámetros height and width con "fill" (rellenar en castellano). Esto le indica al widget que utilice todo el espacio disponible. 

Un ejemplo de uso del valor "fill" con los parámetros height and width puede ser el siguiente:

from guizero import App, PushButton
app = App()
button = PushButton(app, height=10, width=20)
button_sized = PushButton(app, text="Usando todo el espacio", width="fill", height="fill")
app.display()

(No olvides poner las comillas alrededor de fill.)

uso del valor "fill"


No todos los widgets se pueden redimensionar de esta manera. Para ver cual la soportan y cual no, así como otras notas sobre el tamaño de los diferentes widgets consulta la documentación.

CONSEJO

Si tienes problemas para decidir cual debe ser el ancho y/o alto de un widget cuando estés diseñando la aplicación, empieza dibujando todo en un papel (si, si con un lápiz y un papel) e intenta que todos los elementos tengan el tamaño y las proporciones que te gustarían. Si lo haces de esta forma, posteriormente puedes medirlos y pasar esas medidas al programa. 

Ten en cuenta que un carácter mide aproximadamente 0.212 cm y que 600 caracteres tienen una longitud aproximada de 127 cms. Si lo quieres pasar a pixeles tienes que saber que 5.08 cms son unos 600 pixeles. Aunque si lo quieres usar de forma más sencilla, es posible que necesites utilizar un convertidor de unidades como este por ejemplo

Si no te decides por el lápiz y el papel y lo estás diseñando en una aplicación, por norma general el propio programa te facilita alguna opción para obtener el ancho y alto del elemento, pero ahí depende del programa que utilices.

HACIENDO QUE TODO SE ALINEE.

Cuando los widgets se colocan en un contenedor, como en una APP o un Box, en Guizero se pueden colocar de dos formas: automática o usando cuadrículas. De forma automática se utiliza el gestor de geometría PACK y si usamos cuadrículas el gestor de geometría GRID. Aunque por defecto no se contempla también podemos utilizar de forma mixta el gestor de geometría PLACE aunque no lo veremos en este capítulo lo puedes consultar en el correspondiente enlace. Esta elección de diseño es un parámetro inicial para cada contenedor y, por lo tanto, debe especificarse cuando se cree el mismo.

Empezaremos explicando como se colocan los widgets por defecto y en un capítulo posterior veremos como usar cuadrículas (GRID).

Diseño Automático.

Si no especificamos el otro gestor de geometría, por defecto los widgets se colocan de forma automática, en el orden en que se crean, comenzando en la parte superior del contenedor y colocándose en el centro del mismo. (Usan el gestor de geometría Pack)

Los widgets también se pueden alinear a la izquierda, a la derecha o en la parte inferior del contenedor usando el parámetro align. Intenta imaginar como se verá la siguiente aplicación antes de ejecutar el código:

from guizero import App, Text

# El diseño automatico está ya predeterminado.
app = App(title="align")

# Crea una serie de widgets cada uno con una alineación diferente.
top_text = Text(app, text="En la parte de arriba", align="top")
bottom_text = Text(app, text="En la parte de abajo", align="bottom")
left_text = Text(app, text="A la izquierda. ", align="left")
left_text_1 = Text(app, text="A la izquierda de nuevo", align="left")
right_text = Text(app, text="A la derecha", align="right")

app.display()


Cuando se colocan varios widgets en el mismo contenedor y con la misma alineación, aparecen por orden, por lo que left_text aparece primero que left_text_1 en este ejemplo.


colocación automática de los widgets en la ventana


Alineado de Widgtes dentro de un Box.

El alinear widgets dentro de una caja o Box nos va a permitir mejorar mucho el diseño. Un buen ejemplo es la forma de colocar algo en una esquina de la aplicación, en vez de en la parte superior, inferior, derecha o izquierda como hemos hecho hasta ahora.

Mira el código siguiente e intenta adivinar ¿Dónde aparecerá el widget PushButton?


from guizero import App, Box, PushButton
app = App()
box = Box(app, width="fill")
button = PushButton(box, align="left")
app.display()


Se puede usar una caja o Box para mantener los diferentes elementos alineados entre si. Vamos a profundizar un poco más en el concepto intentando usar lo que hemos aprendido para recrear la bandera de un país de Oceanía llamado Tonga. Utilizamos cajas para crear y colocar la cruz y rellenar el resto de la bandera.




Prueba a eliminar los elementos Box de este script (deberás cambiar los parámetros maestros de los otros widgets) y mira lo que se crea cuando se ejecuta, en comparación con la versión con las cajas.

from guizero import App, Text, Box, PushButton, TextBox

app = App(width=300, height=200)
app.bg= "white"

# Divide la bandera en dos secciones, una superior que contendrá la cruz y un bloque rojo inferior.

top = Box(app, align="top", width="fill")
bottom = Box(app, width="fill", height="fill")

# Crea un cuadro para contener la cruz, alineado a la izquierda en la sección superior.
cross = Box(top, align="left")

# Se necesitan dos cajas para construir la cruz.
flag = Box(cross)
# Establece el fondo a blanco.
flag.bg = "white"
# Haz las partes superiores de la cruz con cuatro bloques rojos del mismo tamaño.
first = Text(flag, bg="red", align="top", height=1, width=3)
second = Text(flag, bg="red", align="left", height=1, width=3)
third = Text(flag, bg="red", align="left", height=1, width=3)
fourth = Text(flag, bg="red", align="left", height=1, width=3)
# Crea el segundo cuadro directamente debajo del primero, de modo que la pieza final
# de la cruz se añadirá a la parte inferior de la misma. Intenta ejecutar el
# programa sin esta caja para ver dónde se colocaría automáticamente.
flag_cont = Box(cross)
# Establece el fondo a blanco
flag_cont.bg = "white"
# Completa la bandera
fifth = Text(flag_cont, height=1, width=3, align="bottom", bg="red")

# Rellena el resto de la bandera de color rojo.
fill = Text(top, align="left", height="fill", width="fill", bg="red")
fill_cont = Text(bottom, height="fill", width="fill", bg="red")

app.display()

Puedes encontrar el código superior en el siguiente enlace.


Construyendo un editor de texto.


Con lo que hemos visto hasta ahora vamos a intentar un desafío. Crear un procesador de textos sencillo.  Necesitarás seguramente consultar la documentación de Guizero.

Empecemos.

Primero debemos comenzar planificando que es lo que la aplicación debe hacer y que widgets se adaptan mejor a la tarea. Echa un vistazo a un editor de textos que tengas en tu ordenador para inspirarte (El block de notas puede ser un buen ejemplo, haz clic en el menú archivo para ver algunas opciones que te brinda el editor de texto)

Nuestro editor de texto va a ser muy básico pero tendrá que tener los siguientes elementos:

- Un cuadro de texto para escribir.

- Un cuadro de texto para especificar el nombre del archivo.

- Un PushButton para guardar el archivo.

- Un PushButton para leer los archivos guardados.

Tomate un momento para diseñar el editor de texto incorporando los cuatro elementos. ¿Pondrás el botón Guardar en la parte superior o inferior del GUI? ¿Lo colocarás junto al botón de abrir? ¿Qué tamaño debe tener el cuadro donde se escribirá el texto?

Iremos añadiendo cada uno de los componentes. Intenta modificar el código sobre la marcha para que los widgets se adapten a tu diseño. Recuerda que Guizero coloca los widgets en el orden en el que se crean comenzando desde la parte superior. Eso significa que a lo mejor debes reordenar el código para adaptarlo a tu diseño.

Comienza dibujando en un papel como quieres que sea tu aplicación y luego intenta crear el diseño de la misma. No te preocupes por el código ya que lo desarrollaremos a la vez que iremos explicándolo.


La forma más fácil de manejar los controles y mantenerlos juntos es utilizar una caja (Box).  Yo simplemente la llamaré caja porque vamos a meter ahí los controles de la aplicación pero realmente puedes llamarlo como quieras mientras te quede lo que representa.

from guizero import App, TextBox, PushButton, Box

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

# crea un TextBox para el nombre del archivo
nombreArchivo = TextBox(caja, text="archivo.txt", width=38, align="left")

# Crea un botón Grabar, que se usará con la función para grabar posteriormente.
btn_save = PushButton(caja, text="Grabar",  align="right")

# Crea un botón Leer, que se usará con la función leer posteriormente.
btn_read = PushButton(caja, text="Leer",  align="right")

# Crea un TextBox, el cual no está en la caja y ocupa el resto de la GUI
escritorio = TextBox(app, multiline=True, height="fill", width="fill")

app.display()

Primer diseño del GUI

Por el momento los botones de Grabar y Leer no hacen nada. Para indicarles que guarden o lean un archivo hay que añadir dos funciones:

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

Ambas funciones usan la función "Open" de Python. Si no estás familiarizado con ella puedes encontrar más información aquí.

Antes de seguir leyendo, intenta averiguar cuales son los parámetros nombreArchivo.value y escritorio.value e imagina que hará la función cuando se la llame.

La función push_leer() abre un archivo donde el nombre del mismo coincide con la propiedad del valor del TextBox nombreArchivo. Luego establece que la propiedad del cuadro de texto "escritorio" sea el contenido del archivo, es decir carga el contenido de texto del archivo en el cuadro de texto del escritorio.

La función push_grabar() realiza lo contrario. ¿Puedes deducir cuales son los valores de nombreArchivo.value y escritorio.value en este caso?

Finalmente necesitamos programar a los botones de Grabar y Leer para que ejecuten las funciones respectivas cuando se activen. Esto se hace añadiendo el parámetro "command" a cada uno de los widgets.

btn_save = PushButton(caja, text="Grabar", align="right", command=push_grabar)

¿Puedes escribir el código equivalente para el widget btn_read?

Cuando el procesador esté más avanzado les daremos a los usuarios más opciones de estilo para el texto. Haremos esto en el próximo capítulo así que no olvides guardar el archivo.


Siguiente Capítulo.- 5. Controlando la GUI.