Click here to Skip to main content
16,017,351 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
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?   
Posted
Updated 5-Aug-23 21:24pm
v3

1 solution

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]
 
Share this answer
 
v3
Comments
Tomas Sanchez Garcia 6-Aug-23 7:32am    
Hi, thank you very much.

If it has been solved.

I am very sorry for the inconvenience caused, I am trying to exercise and progress.

I'm learning with OOP and that's why I get a bit stuck, I try to make things more organized.

Thank you very much again, sorry for the inconvenience.
Richard MacCutchan 6-Aug-23 7:43am    
You are welcome, and there is no need to apologize - we all had to learn in the beginning. But I would recommend the Python tutorials as they explain everything quite clearly, and in a number of different languages.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900