viernes, 3 de junio de 2022

¿Cómo usar elementos de Tkinter dentro de Guizero?

 


Uso de elementos de Tkinter dentro de Guizero.

En los ejemplos previos hemos visto como podemos usar widgets o cualquier elemento de Tkinter dentro de un programa de Guizero. Al fin y al cabo Guizero tiene su base en Tkinter con lo que podemos usar todos los widgets de este, dentro de Guizero.

Por ejemplo si creamos una caja de texto en Guizero (Textbox) pero queremos utilizar la propiedad wrap de Tkinter en ese objeto, porque por ejemplo Guizero no la contemplase, podemos asignar ese widget a un a variable y usar la propiedad tk del elemento que está detrás en tkinter (el widget entry). O quizá modificar también el tamaño de la ventana principal usando una propiedad de Tkinter y no la propia de Guizero.

Aunque Guizero es un paquete muy completo a veces no contempla determinados widgets o propiedades de los objetos, que si que están presentes en Tkinter. Por contrapartida es más sencillo de programar.

Lo anterior lo vemos mejor con este ejemplo:

from guizero import App, TextBox, PushButton, Text

def show():
    output.value = textbox.value

app = App()
app.tk.geometry("300x200")
textbox = TextBox(app, multiline=True, height=5, width=50, scrollbar=True, text="a multiline\ntextbox")
textbox.tk['wrap'] = 'word'
button = PushButton(app, text="Print", command=show)
output = Text(app)
app.display()

Aquí utilizamos la propiedad geometry() en app usando app.tk para cambiar el tamaño de la ventana. O textbox.tk[wrap] para cambiar la forma en la que el texto se presenta en la ventana. Esto último se utiliza para ajustar el contenido al ancho de un documento de texto.

Aprovecho para decir que "wrap" admite tres valores.

- none -> no ajusta el texto al ancho. El texto escrito sigue en la misma línea hasta que le des un intro.

- word -> Cuando llegamos al límite derecho del widget, pasa la  palabra entera a la siguiente línea.

- char -> Al llegar al limite derecho del contenedor, pasa el siguiente carácter a la siguiente línea.



Otro ejemplo. 

from guizero import App, Text
from tkinter import Message, HORIZONTAL, BOTH, TOP
from tkinter.ttk import Separator

app=App(title="My gui")
app.tk.geometry("300x200")

message=Text(app, text="A really long string that has too many characters to show up on one line within the default window size")
separador = Separator(app.tk, orient=HORIZONTAL)
separador.pack(side=TOP, fill=BOTH, expand=True,padx=5,pady=5)
msg2 = Message(app.tk, text="A really long string that has too many characters to show up on one line within the default window size")
msg2.pack()
app.display()

Aquí vamos a usar una caja de texto de Guizero para mostrar un texto realmente largo (message). 

Queremos utilizar un separador que es un elemento que si tiene Tkinter pero no esta implementado en Guizero. Lo insertamos al igual que haríamos en Tkinter, teniendo cuidado en definir que su ventana madre es app.tk y no app a secas. Y luego lo posicionamos en la ventana usando pack() de la forma habitual. 

Para terminar usamos el elemento Message de Tkinter para volver a mostrar ese mismo texto. Igual que antes definimos el elemento teniendo cuidado en especificar que su ventana madre es app.tk y luego lo empaquetamos normalmente usando pack().

El resultado:



Pero también hay otra forma de hacerlo. Para ello vamos a ver lo que nos dice el manual de Guizero.


Podemos agregar widgets tk a la aplicación usando el método add_tk_widget() que esta disponible para los elementos app, window y box.

Aquí podemos ver un ejemplo de su aplicación:

from guizero import App, Box, Text
from tkinter import Spinbox, ttk
from tkinter.ttk import Progressbar, Notebook

app = App(title="Using tk widgets")

Text(app, text="Spinbox")

# add a spinbox widget to the app
sp = Spinbox(from_=0, to=10)
app.add_tk_widget(sp)

Text(app, text="and Progressbar")

box = Box(app, border=True)

# add a progress bar to the box
pb = Progressbar(box.tk)
box.add_tk_widget(pb)
pb.start()

Text(app, text="in guizero")

box1 = Box(app, border=True)
nb = Notebook(box1.tk)
# create some frames for the tabs
signal_page_inputs = ttk.Frame(nb)
signal_page_outputs = ttk.Frame(nb)

# add the tabs
nb.add(signal_page_inputs, text='Signal Inputs')
nb.add(signal_page_outputs, text='Signal Outputs')

# important - add tk widget only after it is completed
box1.add_tk_widget(nb)

app.display()
La salida sería la siguiente:



Cuando agregamos un widget de Tkinter a una aplicación, ventana o caja de texto tenemos que especificar la propiedad tk (.tk) al crear el widget.

pb = Progressbar(box.tk)
box.add_tk_widget(pb)
pb.start()
La barra de progreso está dentro del contenedor "Box" así que para usarlo simplemente añadimos la barra de progreso al contenedor (box.add_tk_widget(pb)). 

Usando un método Tkinter en un objeto de Guizero.

Cada widget de Guizero en si mismo, como ya dijimos, es un objeto de Tkinter. Podemos averiguar a cual se corresponde buscando en la página de documentación de Guizero. Por ejemplo un objeto TextBox de Guizero se corresponde con el objeto Entry de Tkinter. Podemos acceder a ese elemento de Tkinter y sus propiedades por tanto usando .tk.

En este ejemplo, tenemos los widgets de Guizero, App y TextBox. Usamos el método config de Tkinter para cambiar el cursor del ratón cuando se sitúe encima del TextBox.

from guizero import App, TextBox app = App() name = TextBox(app, text="Laura") name.tk.config(cursor="target") app.display()





Puedes encontrar el código de los ejemplos en el siguiente enlace.




No hay comentarios:

Publicar un comentario