Sigo aprendiendo cosas (y compartiendo con vosotros) de Tkinter, y hoy toca trabajar con formularios modales personalizados, por supuesto. Para sedimentar mis conocimientos, el ejemplo que he tomado de base es este: http://effbot.org/tkinterbook/tkinter-dialog-windows.htm. Sin embargo, para lo que yo quiero, necesito algunas modificaciones. Este ejercicio aparenta ser muy simple, pero tiene su “truco”.
Formularios modales
Si necesito un formulario modal, es porque requiero de unos datos que deben devolverse a la ventana que lo invoca. y esto es lo que vamos a hacer. Crear un formulario con un botón y una etiqueta, de forma que cuando llame al botón, me solicite un nuevo valor, y dicho valor será el que se mostrará en la etiqueta.
Lo primero, vamos a crear el formulario base, con una clase main, donde creamos lo previsto. Al pulsar el botón, se lanza un evento que llama al formulario modal, que hemos construido con otra clase. Al inicializarlo, le transferimos el valor que queremos modificar. Al ser una variable StringVar, puedes comprobar que mientras escribes, cambia el valor. Si quieres controlar mejor los valores, la solución es “desvincular” el valor a la hora de crear el Entry, y hacer la verificación de valor en la función ok.
Aquí tienes el código completo:
from Tkinter import * class main(Frame): def __init__(self, master): Frame.__init__(self, master=None) self.master.title("Probando Dialogos - Manejando datos") self.master.geometry("300x50") Button(root, text="cambiar valor", command=self.dialogo).pack() self.valor = StringVar() self.valor.set("Hola Manejando datos") Label(self.master, textvariable=self.valor).pack() def dialogo(self): d = MyDialog(root, self.valor, "Probando Dialogo", "Dame valor") root.wait_window(d.top) #self.valor.set(d.ejemplo) class MyDialog: def __init__(self, parent, valor, title, labeltext = '' ): self.valor = valor self.top = Toplevel(parent) self.top.transient(parent) self.top.grab_set() if len(title) > 0: self.top.title(title) if len(labeltext) == 0: labeltext = 'Valor' Label(self.top, text=labeltext).pack() self.top.bind("<Return>", self.ok) self.e = Entry(self.top, text=valor.get()) self.e.bind("<Return>", self.ok) self.e.bind("<Escape>", self.cancel) self.e.pack(padx=15) self.e.focus_set() b = Button(self.top, text="OK", command=self.ok) b.pack(pady=5) def ok(self, event=None): print "Has escrito ...", self.e.get() self.valor.set(self.e.get()) self.top.destroy() def cancel(self, event=None): self.top.destroy() root = Tk() a = main(root) root.mainloop()
Los métodos a tener en cuenta son:
- wait_window es el método que lanza un nuevo formulario
- grab_set es lo que hace al nuevo formulario como modal, de forma que hasta que no se destruye, no vuelve al formulario que lo creó
Espero que os sirva para vuestros proyectos.