Por defecto, una variable definida en una función es de ámbito local a ésta, es decir, no es accesible desde fuera de ésta, dejando de existir en cuanto la función retorne.
Tanto root
como insertNick
son variables definidas en la función NickGui
y por tanto no pueden ser usadas en ObtenerNick
.
Tienes otro error importante:
frame = tk.Frame(root).grid(row=0, column=0, padx=5, pady=5)
al hacer esto, llamar al método grid
/place
/pack
en la misma línea en la que instancias el widget, frame
es el retorno de grid
, que es None
y no una instancia de tkinter.Frame
. Esto hace que a los widget hijos les pases None
como padre:
frame = tk.Frame(root)
frame.grid(row=0, column=0, padx=5, pady=5)
Para solucionar el problema del ámbito de la variables, lo más simple es que definas la callback dentro de NickGui
. De esta forma la función y las variables que usa pertenecen al mismo espacio de nombres y tiene acceso a las mismas:
import tkinter as tk
def nick_gui():
def obtener_nick():
print(nick.get())
root.destroy()
root = tk.Tk()
root.title("Nick")
nick = tk.StringVar()
frame = tk.Frame(root)
frame.grid(row=0, column=0, padx=5, pady=5)
label_nick = tk.Label(frame, text="Inserte su nick y pulse en Listo!")
label_nick.grid(row=1, column=0, columnspan=2, padx=5, pady=5, sticky="n")
insert_nick = tk.Entry(frame, width=30, textvariable=nick)
insert_nick.grid(row=2, column=0, sticky="w", padx=5, pady=5)
boton_nick = tk.Button(frame, text="Listo!", command=obtener_nick)
boton_nick.grid(row=2, column=1, sticky="e", padx=5, pady=5)
root.mainloop()
if __name__ == "__main__":
nick_gui()
No tienes (y no debes) que usar una función anónima si no necesitas pasar parámetros a la función:
Otra posibilidad es pasar las variables como argumento:
import tkinter as tk
def obtener_nick(root, var):
print(var.get())
root.destroy()
def nick_gui():
root = tk.Tk()
root.title("Nick")
nick = tk.StringVar()
frame = tk.Frame(root)
frame.grid(row=0, column=0, padx=5, pady=5)
label_nick = tk.Label(frame, text="Inserte su nick y pulse en Listo!")
label_nick.grid(row=1, column=0, columnspan=2, padx=5, pady=5, sticky="n")
insert_nick = tk.Entry(frame, width=30, textvariable=nick)
insert_nick.grid(row=2, column=0, sticky="w", padx=5, pady=5)
boton_nick = tk.Button(
frame,
text="Listo!",
command=lambda:obtener_nick(root, nick)
)
boton_nick.grid(row=2, column=1, sticky="e", padx=5, pady=5)
root.mainloop()
if __name__ == "__main__":
nick_gui()
Te recomiendo no usar mayúsculas y CamelCase para nombrar variables o funciones. Esto se reserva para las clases por convención (ver Guia de estilo para código Python - PEP 8)
Obviamente existen más formas de solucionar el problema, pero tendríamos que modificar la estructura general de tu código. Por ejemplo, usando programación orientada a objetos:
import tkinter as tk
class NickGui(tk.Frame):
def __init__(self, root, *args, **kwargs):
super().__init__(root, args, **kwargs)
self.root = root
self.root.title("Nick")
self.nick = tk.StringVar()
frame = tk.Frame(root)
frame.grid(row=0, column=0, padx=5, pady=5)
label_nick = tk.Label(frame, text="Inserte su nick y pulse en Listo!")
label_nick.grid(row=1, column=0, columnspan=2, padx=5, pady=5, sticky="n")
insert_nick = tk.Entry(frame, width=30, textvariable=self.nick)
insert_nick.grid(row=2, column=0, sticky="w", padx=5, pady=5)
boton_nick = tk.Button(frame, text="Listo!", command=self.obtener_nick)
boton_nick.grid(row=2, column=1, sticky="e", padx=5, pady=5)
def obtener_nick(self):
print(self.nick.get())
self.root.destroy()
if __name__ == "__main__":
root = tk.Tk()
NickGui(root).place(relwidth=1, relheight=1)
root.mainloop()