El gestor de geometría Grid con Tkinter y Guizero.
Este gestor de ventanas trata las mismas como si fueran una cuadrícula, formada por filas y columnas. El símil podría ser un tablero de ajedrez, donde se pueden situar las piezas, widgets en nuestro caso, dando la referencia de la columna y fila donde queremos colocarlo. Incluso, podemos indicarle a un elemento que ocupe más de una fila o columna.
Con este gestor se pueden construir aplicaciones muy complejas, y hacer que los elementos se adapten a la misma, si las ventanas varían su tamaño.
Tkinter.
Grid con ventana no dimensionable. Ejemplo.
Empezamos con el mismo código que en el capitulo anterior.
from tkinter import *
from tkinter import ttk, font
import getpass
# Gestor de geometría (grid). Ventana no dimensionable
class Aplicacion():
def __init__(self):
self.raiz = Tk()
self.raiz.title("Acceso")
Para hacer que una ventana no sea redimensionable se utiliza el método resizable(0,0) que es la forma abreviada de resizable(width = False, height = False)
self.raiz.resizable(0,0)
fuente = font.Font(weight='bold')
- FLAT (llano)
- RAISED (elevado)
- SUNKEN (hundido)
- GROOVE (hendidura)
- RIDGE (borde elevado)
Luego utilizamos la opción "padding" para conseguir un espacio extra interior y que los widgets no queden pegados al marco. Otra forma sería usar padx y pady con cada uno de los widgets que usamos dentro del marco.
self.marco = ttk.Frame(self.raiz, borderwidth=2,
relief="raised", padding=(10,10))
Diseñaremos todos los elementos de la ventana con la diferencia de que los vamos a situar dentro del Frame (marco) que hemos creado.
self.etiq1 = ttk.Label(self.marco, text="Usuario:",
font=fuente, padding=(5,5))
self.etiq2 = ttk.Label(self.marco, text="Contraseña:",
font=fuente, padding=(5,5))
# Define variables para las opciones 'textvariable' de
# cada caja de entrada 'ttk.Entry()'.
self.usuario = StringVar()
self.clave = StringVar()
self.usuario.set(getpass.getuser())
self.ctext1 = ttk.Entry(self.marco, textvariable=self.usuario,
width=30)
self.ctext2 = ttk.Entry(self.marco, textvariable=self.clave,
show="*",
width=30)
self.separ1 = ttk.Separator(self.marco, orient=HORIZONTAL)
self.boton1 = ttk.Button(self.marco, text="Aceptar",
padding=(5,5), command=self.aceptar)
self.boton2 = ttk.Button(self.marco, text="Cancelar",
padding=(5,5), command=quit)
Ahora viene la parte interesante, que es el colocar los elementos en las casillas o cuadrículas dentro del marco. En realidad habrá dos cuadrículas. Una de una fila por una columna que está en la ventana que ocupará el Frame (marco) y otra de cinco filas por tres columnas que ocuparán el resto de los widgets. Ten en cuenta que las filas y columnas se empiezan a contar en el cero.
self.marco.grid(column=0, row=0)
self.etiq1.grid(column=0, row=0)
self.ctext1.grid(column=1, row=0, columnspan=2)
self.etiq2.grid(column=0, row=1)
self.ctext2.grid(column=1, row=1, columnspan=2)
self.separ1.grid(column=0, row=3, columnspan=3, sticky="ew")
self.boton1.grid(column=1, row=4)
self.boton2.grid(column=2, row=4)
El diseño es algo como esto:
El resto del código es igual al del otro capítulo.
# Establece el foco en la caja de entrada de la
# contraseña.
self.ctext2.focus_set()
self.raiz.mainloop()
def aceptar(self):
if self.clave.get() == 'herodoto':
print("Acceso permitido")
print("Usuario: ", self.ctext1.get())
print("Contraseña:", self.ctext2.get())
else:
print("Acceso denegado")
self.clave.set("")
self.ctext2.focus_set()
def main():
mi_app = Aplicacion()
return 0
if __name__ == '__main__':
main()
En el siguiente enlace puedes encontrar el código del programa.
Grid con ventana dimensionable.
Tamaño standar.
Redimensionada.
Lo que vamos a ver ahora es como hacer lo mismo, pero cuando la ventana es dimensionable y tenemos que adaptar los widgets a ese aumento o disminución del tamaño de la ventana que los contiene.
El comienzo es el mismo que en el caso anterior. La parte que variará será a partir de que definamos la posición de los widgets en el marco.
from tkinter import *
from tkinter import ttk, font
import getpass
'''Gestor de geometría (grid). Ventana dimensionable'''
class Aplicacion():
def __init__(self):
self.raiz = Tk()
self.raiz.title("Acceso")
fuente = font.Font(weight='bold')
self.marco = ttk.Frame(self.raiz, borderwidth=2,
relief='raised', padding=(10,10))
# Define el resto de widgets pero en este caos el primer
# parámetro indica que se situarán en el widget del marco
# anterior 'self.marco'.
self.etiq1 = ttk.Label(self.marco, text="Usuario:",
font=fuente, padding=(5,5))
self.etiq2 = ttk.Label(
self.marco, text="Contraseña:", font=fuente, padding=(5,5))
# Define variables para las opciones 'textvariable' de
# cada caja de entrada 'ttk.Entry()'.
self.usuario = StringVar()
self.clave = StringVar()
self.usuario.set(getpass.getuser())
self.ctext1 = ttk.Entry(self.marco, textvariable=self.usuario, width=30)
self.ctext2 = ttk.Entry(self.marco, textvariable=self.clave, show="*", width=30)
self.separ1 = ttk.Separator(self.marco, orient=HORIZONTAL)
self.boton1 = ttk.Button(self.marco, text="Aceptar", padding=(5,5), command=self.aceptar)
self.boton2 = ttk.Button(self.marco, text="Cancelar", padding=(5, 5), command=quit)
Para conseguir que cuando se amplíe o reduzca el tamaño de la ventana los widgets se adapten al mismo hay que introducir el parámetro "sticky", que viene del termino "pegajoso" en inglés.
Cuando un widget se coloca en su cuadrícula lo hace en la parte central de la misma, la cual se adapta a su tamaño. Al usar este parámetro le estamos diciendo como tiene que comportarse cuando se modifiquen las dimensiones de la ventana. Se usan como valores los puntos cardinales en ingles: N (norte), S (sur), E (este) y W (oeste) solos o de forma combinada. El widget se quedará pegado a los lados de su celda en las direcciones que se indiquen. Aunque esto solo no basta, además de definir los stickies hay que activarlos, lo cual veremos en los siguientes pasos.
Comencemos definiendo el sticky para cada uno de los elementos
self.marco.grid(column=0, row=0, sticky=(N,S,E,W)) self.etiq1.grid(column=0, row=0, sticky=(N,S,E,W)) self.ctext1.grid(column=1, row=0, columnspan=2, sticky=(E,W)) self.etiq2.grid(column=0, row=1, sticky=(N,S,E,W)) self.ctext2.grid(column=1, row=1, columnspan=2, sticky=(E,W)) self.separ1.grid(column=1, row=3, columnspan=3, sticky="nsew") self.boton1.grid(column=1, row=4,sticky=(E)) self.boton2.grid(column=2, row=4,sticky=(W))
# Repartimos el peso en cada contenedor.
self.raiz.columnconfigure(0, weight=1)
self.raiz.rowconfigure(0, weight=1)
self.marco.columnconfigure(0, weight=1)
self.marco.columnconfigure(1, weight=1)
self.marco.columnconfigure(2, weight=1)
self.marco.rowconfigure(0, weight=1)
self.marco.rowconfigure(1, weight=1)
self.marco.rowconfigure(4, weight=1)
# Establece el foco en la caja de entrada de la contraseña self.ctext2.focus_set() self.raiz.mainloop() def aceptar(self): if self.clave.get()=='herodoto': print('Acceso Permitido') print('Usuario: ', self.ctext1.get()) print('Contraseña: ', self.ctext2.get()) else: print('Acceso denegado') self.clave.set("") self.ctext2.focus_set() def main(): mi_app = Aplicacion() return 0 if __name__=='__main__': main()
El gestor de geometría Grid con Guizero.
from guizero import *
#HORIZONTAL is Tkinter's variable. If you want to use it you have to import it or have to use like Tkinter.HORIZONTAL
#If you dont want to add Tkinter then you can do from Tkinter import HORIZONTAL
from tkinter import HORIZONTAL
# CUALQUIER VARIABLE DE TK QUE NO APAREZCA HAY QUE IMPORTARLA.
from tkinter.ttk import Separator #Importamos el widget que necesitemos de ttk
from getpass import getuser
def aceptar():
if ctext2.value == 'herodoto':
print('Acceso Permitido')
print('Usuario: ', ctext1.value)
print('Contraseña: ', ctext2.value)
ctext2.value="" #Borra el contenido del 2º cuadro de texto
quit() #Sale del programa
else:
print('Acceso denegado')
ctext2.value="" # Borra el contenido del 2º cuadro de texto si se falla.
usuario = getuser() # Captura el nombre del usuario que usa el sistema.
raiz = App(width=390, height=120, title="Acceso") raiz.tk.resizable(0, 0) # Es otra forma de decirle que la ventana es fija y no se puede cambiar el tamaño. marco_sup = Box(raiz) # Creamos un marco normal, que se coloca arriba Text(marco_sup, text="", size=5) # Pongo esto para separar lo siguiente del borde superior. marco = Box(raiz, layout="grid") # el marco usará (3 columnas x 5 filas) grid. # el tamaño de cada celda viene determinado por lo que contiene dentro. etiq1 = Text(marco, text="Usuario", grid=[0, 0], align='left', font='padmaa-Bold.1.1', size=14) ctext1 = TextBox(marco, grid=[1, 0, 2, 1], width=30, align='left') # lo alineamos a la izquierda dentro del grid. etiq1 = Text(marco, text="Contraseña", grid=[0, 1], align='left', font='padmaa-Bold.1.1', size=14) # size es el tamaño de la letra ctext2 = TextBox(marco, grid=[1, 1, 2, 1], width=30, hide_text=True) # hide_text=True cambia las letras por * # grid=[1,1,2,1] situa el grid en la columna 1 y fila 1 y luego lo expande 1 columnas y 0 fila (sumamos 1 a lo q queremos expandir) # El grid no admite [1,1,0,0], xq por defecto el grid [1,1] es como si fuera [1,1,1,1] #x lo que expandir una columna seria [1,1,2,1] o expandir una fila [1,1,1,2] #------------------------------------------------------------------------------------------ separ1 = Separator(marco.tk, orient=HORIZONTAL) separ1.grid(column=1, row=3, columnspan=3, sticky="ew") '''Para que un widget de tk o ttk funcione en guizero hay que diseñarlo y luego pack o grid o el gestor de geometria que se use''' #-------------------------------------------------------------------------------------------- boton1 = PushButton(marco, grid=[1, 4], text='Aceptar', padx=16, pady=6, command=aceptar) boton2 = PushButton(marco, grid=[2, 4], text='Cancelar', padx=16, pady=6, command=quit) ctext1.value=usuario ctext2.focus() # Pone el foco en el cuadro 2 donde pondremos la contraseña. raiz.display()
No hay comentarios:
Publicar un comentario