Hi, I have a problem. I'm trying to close the main window when logging in, with destroy(), but it throws me an error, why? what am I doing wrong? How can I solve it? Any additional information would be appreciated.
The error that I get when I press the button and want to close the window is the following:
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/tkinter/__init__.py", line 1948, in __call__
return self.func(*args)
^^^^^^^^^^^^^^^^
File "/Users/tomassanchezgarcia/Desktop/python-test/iniciar_sesion.py", line 84, in validar
self.root.destroy()
^^^^^^^^^
AttributeError: 'Login' object has no attribute 'root'
main.py
Python
from tkinter import * from tkinter import ttk import tkinter as tk import pymysql from conexion import * from tkinter import messagebox from PIL import Image, ImageTk from iniciar_sesion import Login class AplicacionInventario: def __init__(self): self.root = Tk() self.root.title( " StockMaster" ) self.root.geometry( " 400x500" ) # Bloquear agrandar ventana self.root.resizable( 0 , 0 ) self.wtotal = self.root.winfo_screenwidth() self.htotal = self.root.winfo_screenheight() # Guardamos el largo y alto de la ventana self.wventana = 400 self.hventana = 500 # # Aplicamos la siguiente formula para calcular donde debería posicionarse self.pwidth = round (self.wtotal/2-self.wventana/2) self.pheight = round (self.htotal/2-self.hventana/2) # Se lo aplicamos a la geometría de la ventana self.root.geometry( str (self.wventana)+ " x" + str (self.hventana)+ " +" + str (self.pwidth)+ " +" + str (self.pheight)) self.imagen = Image. open ( " src/logo.png" ) self.imagen = self.imagen.resize(( 350 , 100 )) # Opcional: Redimensionar la imagen self.imagen = ImageTk.PhotoImage(self.imagen) # Crear un widget Label con la imagen y colocarlo en la ventana self.label_imagen = tk.Label(self.root, image=self.imagen) self.label_imagen.pack(pady=20) self.login1 = Login(self) # fetch_data_button = tk.Button(self.root, text="Obtener Datos", command=self.mostrar2) # fetch_data_button.pack() self.root.mainloop() AplicacionInventario()
iniciar_sesion.py
Python
from tkinter import * from tkinter import ttk import tkinter as tk import pymysql from conexion import * from tkinter import messagebox from PIL import Image, ImageTk from test2 import Menus class Login: def __init__(self, app): self.app = app self.t_Email = " Email:" self.label_email = tk.Label(text=self.t_Email) self.label_email.pack(pady=5, padx=20) self.label_email.place(x=150, y=150, width=100, height=20) self.entry_email = tk.Entry() self.entry_email.pack(pady=5) self.entry_email.place(x=75, y=170, width=250, height=50) self.t_Password = " Contraseña:" self.label_password = tk.Label(text=self.t_Password) self.label_password.pack(pady=5, padx=20) self.label_password.place(x=150, y=220, width=100, height=20) self.entry_password = tk.Entry(show= " *" ) self.entry_password.pack(pady=5) self.entry_password.place(x=75, y=240, width=250, height=50) self.login_email = self.entry_email.get() self.login_password = self.entry_password.get() self.boton_login = tk.Button(text= " Iniciar Sesión" , command=self.validar) self.boton_login.pack(pady=5) self.boton_login.place(x=125, y=300, width=150, height=50) def validar(self): # self.conexion_login = connect_to_database() # self.cursor_conexion_login = self.conexion_login.cursor() # self.cursor_conexion_login.execute("SELECT email, password FROM usuarios WHERE email=%s AND password=%s", (self.login_email, self.login_password)) # self.verificar_login = self.cursor_conexion_login.fetchall() # messagebox.showwarning("Advertencia", self.verificar_login) # Conectarse a la base de datos utilizando la función importada self.connection2 = connect_to_database() self.cursor2 = self.connection2.cursor() # Ejemplo: Ejecutar una consulta para obtener datos self.cursor2.execute( " SELECT nombre,password FROM usuarios" ) self.data2 = self.cursor2.fetchall() # messagebox.showwarning("Advertencia", self.data2) # Cerrar el cursor y la conexión for self.fila in self.data2: self.v_email = self.fila[ 0 ] self.v_password = self.fila[ 1 ] self.cursor2.close() self.connection2.close() if self.entry_email.get() == " " or self.entry_password.get() == " " : self.dialogo = tk.Toplevel() self.dialogo.title( " Diálogo Personalizado" ) self.dialogo.geometry( " 300x50" ) self.dialogo.resizable( 0 , 0 ) self.wtotal2 = self.dialogo.winfo_screenwidth() self.htotal2 = self.dialogo.winfo_screenheight() self.wventana2 = 300 self.hventana2 = 50 self.pwidth2 = round (self.wtotal2/2-self.wventana2/2) self.pheight2 = round (self.htotal2/2-self.hventana2/2) self.dialogo.geometry( str (self.wventana2)+ " x" + str (self.hventana2)+ " +" + str (self.pwidth2)+ " +" + str (self.pheight2)) self.etiqueta = tk.Label(self.dialogo, text= " Este es un cuadro de diálogo personalizado." , padx=10, pady=10) self.etiqueta.pack() elif self.entry_email.get() == self.v_email and self.entry_password.get() == self.v_password: # messagebox.showwarning("Advertencia", "PERFECTO COINCIDE") self.ventana_menu = Menus(self) else: self.root.destroy() messagebox.showwarning( " Advertencia" , " Los datos introducidos son incorrectos." )
What I have tried:
how could i solve it?    Similar issues to your previous question on this subject. The object named root belongs to the AplicacionInventario class. When you call Login(self) the login object is created, but the attribute named root is not passed over to it, hence the error. However, you do have a reference to the AplicacionInventario object, in the app parameter that is passed in. So change that line to:
Python
self.app.root.destroy()
and it should work.
[edit]
I would suggest reading 9. Classes — Python 3.11.4 documentation [ ^ ] where it explains objects, scope and namespaces, in some detail.
[/edit]
  • Read the question carefully.
  • Understand that English isn't everyone's first language so be lenient of bad spelling and grammar.
  • If a question is poorly phrased then either ask for clarification, ignore it, or edit the question and fix the problem. Insults are not welcome.
  • Don't tell someone to read the manual. Chances are they have and don't get it. Provide an answer or move on to the next question. Let's work to help developers, not make them feel stupid.
  •