jueves, 1 de agosto de 2024

pyTermTk y ttkDesigner: Button y Lablel

No lo vamos a negar, pyTermTk me ha encantado. Siempre hemos tenido ganas de poder hacer el terminal un poquito más amigable, pero no siempre es una tarea sencilla.

Ya hemos visto como instalar pyTermTk y ttkDesigner. Ahora veremos como funciona, accedemos al programa desde la terminal con el comando:


$ttkDesigner

A partir de aquí, tenemos la pantalla dividida en secciones:

  • Lista de elementos:

    Tenemos muchos de donde escoger, Layouts, Containers, Buttons, etc... Solo tenemos que mantener pulsado el elemento y arrastrar hacia el marco principal

  • Árbol de inspección:

    Todos los elementos que adjuntemos al proyectos ordenados por jerarquía

  • Propiedades del widget:

    Son las características de cada elemento, tales como alto, ancho, posición, etc...

  • Editor de Signal y slots:

    Se emite una señal cuando se produce un evento en particular.
    Un slot es una función que se llama en respuesta a una señal particular.
    TermTk TTkWidgets tiene muchas signals y slots predefinidos, pero es posible crear una subclase a cualquier TTkWidgets y añadir nuestras propias signals/slots. En este ejemplo solo usaremos los slots.



  • Logs:

    Registro de lo que pasa en el programa en tiempo de ejecución

  • File:

    Estas son las opciones clásicas, abrir, guardar, importar, exportar. Los archivos se guardan en formato JSON.

  • Edit:

    También cuenta con opciones como deshacer rehacer, Otra opción es KeypressView que nos abrirá una pequeña ventana que nos muestra que tecla hemos pulsado.

  • Preview:

    Muestra una vista previa de la interfaz que estamos creando:

  • Quick export:

    Con quick export, exportaremos el proyecto de una manera sencilla y tenemos varias opciones para hacerlo, Normal y Compressed En la parte superior izquierda nos aparece un icono de disquete . Al pulsar sobre el nos aparece una pantalla donde podemos guardar la interfaz en formato estándar .py. Luego podemos modificarlo a nuestro antojo con cualquier editor de texto:

    Normal: Al pulsar sobre la opción Normal nos aparece el código de una manera legible podemos ver como esta estructurado.

    Compressed: Muestra el mismo código pero de una manera comprimida. Con esta opción no podemos leer nada del código. La parte positiva es que es más fácil a la hora de copiar y pegar ya que siempre usa la misma estructura a diferencia de JSON

  • Vista en contraste:

    La vista de los elementos cambia a bloques para para poder ver mejor su posición relativa en la pantalla. Es muy útil para ver donde están situados exactamente los bloques y dejarlos justo donde queramos que estén



from TermTk import TTkUtil, TTkUiLoader, TTk

# Data generated using ttkDesigner
widget = TTkUiLoader.loadDict(TTkUtil.base64_deflate_2_obj(
    "eJx1kt9r1EAQxxOTXC620qq10hb0xJd7Og7xoa34YA9/4HpSMFhQfNgmy83S3O6RZLUVCj5eYR7X/9fZJFcFaZawMzu7s5+Z7/4Kf+8HXvNd2iHG30VZSa0sRs9G49HY" +
    "YlAbaV0oygpeVRbX0/RsolXNpRKlxd6Cl3xeNVvCj3wuLN6eUuxEqlz/sNg/1pWsXcpvdshCdktg+En+FI37hW0KTKZSDU5kXoNlHh0m752QM6idm0z5eRd873m+i9NC" +
    "F29X4s+ykqeFsEuMXytOVu7MVOsilQuLnsX4mOe5VLPmUq8dAnsf+IU2tcWESupsg72itaggiGAX4ksq4q3Qc1GXF91x4q5thf0MZJGXwtXWbG8ydZW7g0NI4CmsuVt3" +
    "WCDgjrOesETABvNgk/67TQ1wr53uL2FrCQ9gGx66nQHz3RCwA7vYO9JlTh1fYpTKmsqFbVxv7xq8Kfiscu3w+gb2/iGHRy3wYxYRMAwo61/QI1PXpMsKdNyCRiRRC7rl" +
    "kDdYn0CDm0AxTMU5tbC3SjZcYjIBkZ05IewVxo1DklwZDErqC4kaZLpwc0x+teDKMh9jWuts0yL2G1VORXFN+HJF6F8T+o4wIkL/xlY+x6hNg9FEF5rebLj3dTwn2V8V" +
    "cqbmQtFLCw3skxwH9B9SrhdEIf5f4sbgWqaVEpl70hXpbkZ/AFN2DDk="))

root=TTk()
root.layout().addWidget(widget)
root.mainloop()

Ya tenemos el código básico, ahora vamos a transformarlo en una clase. Para la clase tenemos que pasarle el tipo del elemento principal. En TTkDesigner viene indicado en el árbol de inspección:



from TermTk import TTkUtil, TTkUiLoader, TTk, TTkContainer

class Interfaz_Label(TTkContainer):
	def __init__(self):
    		TTkUiLoader.loadDict(TTkUtil.base64_deflate_2_obj(
    "eJx1kt9r1EAQxxOTXC620qq10hb0xJd7Og7xoa34YA9/4HpSMFhQfNgmy83S3O6RZLUVCj5eYR7X/9fZJFcFaZawMzu7s5+Z7/4Kf+8HXvNd2iHG30VZSa0sRs9G49HY" +
    "YlAbaV0oygpeVRbX0/RsolXNpRKlxd6Cl3xeNVvCj3wuLN6eUuxEqlz/sNg/1pWsXcpvdshCdktg+En+FI37hW0KTKZSDU5kXoNlHh0m752QM6idm0z5eRd873m+i9NC" +
    "F29X4s+ykqeFsEuMXytOVu7MVOsilQuLnsX4mOe5VLPmUq8dAnsf+IU2tcWESupsg72itaggiGAX4ksq4q3Qc1GXF91x4q5thf0MZJGXwtXWbG8ydZW7g0NI4CmsuVt3" +
    "WCDgjrOesETABvNgk/67TQ1wr53uL2FrCQ9gGx66nQHz3RCwA7vYO9JlTh1fYpTKmsqFbVxv7xq8Kfiscu3w+gb2/iGHRy3wYxYRMAwo61/QI1PXpMsKdNyCRiRRC7rl" +
    "kDdYn0CDm0AxTMU5tbC3SjZcYjIBkZ05IewVxo1DklwZDErqC4kaZLpwc0x+teDKMh9jWuts0yL2G1VORXFN+HJF6F8T+o4wIkL/xlY+x6hNg9FEF5rebLj3dTwn2V8V" +
    "cqbmQtFLCw3skxwH9B9SrhdEIf5f4sbgWqaVEpl70hXpbkZ/AFN2DDk="), self)

root=TTk()
root.layout().addWidget(Interfaz_Label())
root.mainloop()



Ahora que ya tenemos la interfaz diseñada vamos a crear los objetos para cada elemento de la pantalla y de esta manera poder interactuar con ellos.
Aquí es donde entran en juego las signals y los slots. Para usar los slots hay que importar la librería pyTTkSlot. Será como los widgets se comuniquen entre ellos y con el programa principal.

En este ejemplo al llamar a mi_función antes tenemos que poner pyTTkSlot() indicando si el dato que pasamos es, por ejemplo, un String o un valor entero.



# Importamos pyTTkSlot
from TTkTerm import pyTTkSlot


# Para una función que recibe un string:

pyTTkSlot(str)
def mi_funcion(data):
	# Imprime el resultado
	print(data)
	

# Para una función que recibe un valor entero:

pyTTkSlot(int)
def mi_funcion(valor):
	# Imprime el resultado
	print(str(valor))


Ahora solo tenemos que aplicar esta función al botón bt1


from TermTk import TTkUtil, TTkUiLoader, TTk, TTkContainer
from TermTk import pyTTkSlot

class Interfaz_Label(TTkContainer):
	def __init__(self):
    		TTkUiLoader.loadDict(TTkUtil.base64_deflate_2_obj(
    "eJx1kktv1DAQgBOSbDa0UB6lqK0Ey217WS0cOPA40BUP1SyqREQlEAdvYu1YzdqrxIEWqRLHrTRH838ZJykFocaKPA97/M3jZ/jrIPCa78wOMf4mykpqZTF6MhqPxhYD" +
    "U0vrXFFW8KqyuJ6mxxOtDJdKlBZ7S17yRdUcCT/whbB4fUq+I6ly/d1i/1BX0riQX+2QheyawPCj/CEa9TO7KTCZSjU4krkByzy6TNo7IedgnJpM+UnnPPA83/nJ0Plb" +
    "S/xJVnJWCLvC+LXiJOVOTLUuUrm06FmMD3meSzVvHvXaJbD3np/q2lhMKKVOrrFXtBIlBBHsQHxGSbwVeiFMedpdJ25jK+xnIIu8FC635ngTqcvcXRxC8o9pzb2/zQIB" +
    "N5z0iCUCNpgHt+i/3WQDd9rt7go2V3APtuC+Oxkw3y0B27CDvX1d5lT7FUapNJQ4bOF6+8TgTcHnlSuM169h968c4EGL/pBFhA4DinqJvF8bQx26QA5m5nEHG1HDWthN" +
    "h73B+gQbXAWLYSpOqKC9i4B7K0wmILJj1xZ7jnGjUIPOawxKKgm1OMh04faY9GrJlWU+xmTr5LrF7Dc9monikrKYXVL6fyh9RxkRpX9lSZ9i1IbCaKILTVMc7n4ZL2gQ" +
    "XhVyrhZC0eyFNTyjtjyn/wXFekkk4n8Tr2tcy7RSInNDXtEk1KPfcuQTkg=="), self)
		
    	    self.window = self.getWidgetByName("TTkWindow")
    	    self.window.setTitle("Titulo ventana")
        
    	    self.bt1 = self.getWidgetByName("bt1")
            self.bt1.clicked.connect(lambda : self.cambiar_label("Hola!!!"))
            
    	    self.lb1 = self.getWidgetByName("lb1")
    
	pyTTkSlot(str)
	def cambiar_label(self, data):
		self.lb1.setText(data)
        self.bt1.setText("Pulsado!")


	
root=TTk()
root.layout().addWidget(Interfaz_Label())
root.mainloop()


 

 

Y eso es todo en nuestra introducción a la librería pyTermTk y su TUI. Ya no hay excusas para crear interfaces de usuario en la terminal, ahora es más sencillo de lo que parece gracias a esta librería. Su arquitectura modular y la posibilidad de crear widgets personalizados te permiten adaptar la librería a tus necesidades más específicas. Os animo a experimentar con ella y recordar que hay una amplia documentación sobre esta librería en GitHub.


Programa de ejemplo de este articulo en GitHub

Librería PyTermTk crea interfaces en terminal

Repositorio oficial pyTermTk

Diseñador de Interfaces de Texto TTkDesigner 

Saludos!!!


No hay comentarios :

Publicar un comentario