0

Using this code as a guide to try and make something of my own:

https://stackoverflow.com/a/49325719/9543223

Trying to use the switch_frame function to set a new frame when a tkinter Toplevel widget is destroyed. The switching process is working, or at least its putting one frame in front of the other, however, I get this error at the end:

line 49, in switch_frame self.frame.destroy() AttributeError: 'function' object has no attribute 'destroy'

Now, I'm no expert, so its hard for me to follow all these 'self's... So I'm not quite sure why it can't destroy the previous frame... Is there something I need to change because I'm referencing the swtich_frame function inside another function in another class?

Here's my code:

import os
import tkinter as tk
from tkinter import ttk
import sys
import time



Users = [('Admin','AdminPassword')]

class main_window(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.title('Pilot Flight and Duty Tracker')
        self.geometry('1000x700+250+50')
        self.resizable(width = False, height = False)
        self.frame = None
        self.switch_frame(Blank_Frame)
        Login_Window = Login(self)



    def switch_frame(self, frame_class):
        new_frame = frame_class()
        if self.frame is not None:
            self.frame.destroy()
            self.frame = new_frame
            self.frame.pack()
        else:
            self.frame = new_frame
            self.frame.pack()




class Login(tk.Toplevel):
    def __init__(self, master, *args, **kwargs):
        tk.Toplevel.__init__(self, master, *args, **kwargs)
        self.resizable(width = False, height = False)
        self.title('User Login')
        self.attributes('-topmost', True)
        self.geometry('230x200+625+275')
        self.grab_set()
        self.transient(master)
        userlabel = tk.Label(self, text="Employee ID:", font='arial 10 bold')
        userlabel.place(x=25, y=5)
        self.user_entry = tk.Entry(self, relief='groove', width=25, font='arial 10', bd=1)
        self.user_entry.place(x=25, y=30)
        passwordlabel = tk.Label(self, text="Password:", font='arial 10 bold')
        passwordlabel.place(x=25, y=70)
        self.password_entry = tk.Entry(self, relief='groove', width=25, font='arial 10', show="*", bd=1)
        self.password_entry.place(x=25, y=95)
        self.warn = tk.Label(self, font='arial 10 bold', relief='sunken', width=25)
        self.warn.place(x=12, y=121)
        button = tk.Button(self, text="Login", relief='groove', width=12, font='arial 15 bold', justify='center', command=self.login)
        button.place(x=38, y=150)


    def login(self):
        global Users
        username = self.user_entry.get()
        pw = self.password_entry.get()
        if (username, pw) in Users:
            if (username, pw) == ('Admin', 'AdminPassword'):
                self.warn.config(text='Login Successful!', bg='green', justify='center')
                self.after(500, self.destroy)
                main_window.switch_frame(main_window, First_Login)
            else:
                self.warn.config(text='Login Successful!', bg='green', justify='center')
                self.after(500, self.destroy)
        else:
            self.warn.config(text="Invalid Username or Password", fg="black", bg='red', justify ='center')

class Blank_Frame(tk.Frame):
    def __init__(self):
        tk.Frame.__init__(self, width=1000, height=700)


class First_Login(tk.Frame):
    def __init__(self):
        tk.Frame.__init__(self, width=300, height=700, bg='grey60', relief='ridge', bd=3)
        self.place(anchor='nw', x=350)
        usercreationlabel = tk.Label(self, text='New User Creation', font='arial 20 bold', justify='center', bg='grey60')
        usercreationlabel.place(anchor='nw', x=25)
        newuserlabel = tk.Label(self, text='Employee Number:', font='arial 10 bold', bg='grey70', relief='sunken', width=17, justify='center')
        newuserlabel.place(anchor='nw', x=3, y=40)
        self.newuserentry = tk.Entry(self, font='arial 10 bold', width=10, relief='sunken', bd=2, justify='center')
        self.newuserentry.place(anchor='nw', x=35, y=63)
        newpasswordlabel = tk.Label(self, text='Enter New Password:', font='arial 10 bold', bg='grey70', relief='sunken', width=17)
        newpasswordlabel.place(anchor='nw', x=149, y=40)
        self.newpasswordentry = tk.Entry(self, font='arial 10 bold', width=19, relief='sunken', bd=2)
        self.newpasswordentry.place(anchor='nw', x=150, y=63)



run = main_window()
run.mainloop()

Can anyone tell me why I'm getting this error, what it means, and how to get rid of it? Thanks!

1 Answers1

0

The problem is that you're passing a function into switch_frame. You need to pass the instance of main_window. So two changes will fix this.

class Login(tk.Toplevel):
    def __init__(self, master, *args, **kwargs):
        tk.Toplevel.__init__(self, master, *args, **kwargs)
        # Add this line.
        self.master = master
        ...

In the login method, change the main_window.switch_frame statement to:

main_window.switch_frame(self.master, First_Login)
Ron Norris
  • 2,642
  • 1
  • 9
  • 13