0

I am trying to return a value from an Entry widget from another class.

My idea is, when the user has logged in successfully, the welcome screen will show the username that has just logged in.

I have tried using this:

    self.userLogged = Label(main, text = self.entry_username.get())
    self.userLogged.pack()

i tried linking >self.entry.entry_username.get() from the login class. But here is the error code:

AttributeError: 'App' object has no attribute 'entry_username'

Where I'm I going wrong?

Here is the full code:

from tkinter import *
import tkinter.ttk as ttk


class App():
    def __init__(self,master):


        notebook = ttk.Notebook(master)
        notebook.pack(expand = 1, fill = "both")

        #Frames
        main = ttk.Frame(notebook)


        notebook.add(main, text='Welcome Screen')




        self.userLogged = Label(main, text = self.entry_username.get())
        self.userLogged.pack()





###################################################################################################################################
                                                        ##USERS##
###################################################################################################################################
class login(Frame):
    def __init__(self, master):
        super().__init__(master)

        self.label_username = Label(self, text="Username: ",font=("bold",16))
        self.label_password = Label(self, text="Password: ",font=("bold",16))

        self.entry_username = Entry(self, font = ("bold", 14))
        self.entry_password = Entry(self, show="*", font = ("bold", 14))



        self.label_username.grid(row=0, sticky=E)
        self.label_password.grid(row=1, sticky=E)
        self.entry_username.grid(row=0, column=1)
        self.entry_password.grid(row=1, column=1)

        self.logbtn = Button(self, text="Login", font = ("bold", 10), command=self._login_btn_clicked)
        self.logbtn.grid(columnspan=2)

        self.pack()


    def _login_btn_clicked(self):
        # print("Clicked")
        username = self.entry_username.get()
        password = self.entry_password.get()

        # print(username, password)
        account_list = [line.split(":", maxsplit=1) for line in open("passwords.txt")]
        # list of 2-tuples. Usersnames with colons inside not supported.
        accounts = {key: value.rstrip() for key, value in account_list}
        # Convert to dict[username] = password, and slices off the line ending.
        # Does not support passwords ending in whitespace.

        if accounts[username] == password:
            self.label_username.grid_forget()
            self.label_password.grid_forget()
            self.entry_username.grid_forget()
            self.entry_password.grid_forget()
            self.logbtn.grid_forget()
            self.pack_forget()
            app = App(root)
        else:
            print("error")





root = Tk()
root.minsize(950, 450)
root.title("test")

lf = login(root)
root.mainloop()

2 Answers2

0

Firstly, you should change class name from class login(Frame) to class Login(Frame).

Before fixing it, you called the login function from App, but you need to call Login class and use it.

class App:
    def __init__(self, master):
        notebook = ttk.Notebook(master)
        notebook.pack(expand=1, fill="both")

        # Frames
        main = ttk.Frame(notebook)

        notebook.add(main, text='Welcome Screen')

        # `entry_username.get()` method is owned by the Login class,
        # so you need to call from not `self(App class)` but `login(Login class)`.
        login = Login(master)  # Call Login class
        self.userLogged = Label(main, text=login.entry_username.get())  
        self.userLogged.pack()

With this fix, I could call the Welcome screen.

luthierBG
  • 164
  • 1
  • 9
  • this shows me the Login frame at the bottom of main screen when logged in. –  Sep 27 '19 at 14:06
0

When working with multiple classes in tkinter it is often a good idea to use class inherancy for the main window and frames. This allows us to use self.master to interact between classes.

That said you have a few things to change. You are using self where it is not needed and you should be doing import tkinter as tk to prevent overwriting of methods.

I have added a class to your code so we use one class for the root window. Then use one class for the login screen and then use one class for the frame after login.

import tkinter as tk
import tkinter.ttk as ttk


class NotebookFrame(tk.Frame):
    def __init__(self, username):
        super().__init__()
        notebook = ttk.Notebook(self)
        notebook.pack(expand=1, fill="both")
        main = ttk.Frame(notebook)
        notebook.add(main, text='Welcome Screen')
        tk.Label(main, text=username).pack()


class Login(tk.Frame):
    def __init__(self):
        super().__init__()
        tk.Label(self, text="Username: ", font=("bold", 16)).grid(row=0, sticky='e')
        tk.Label(self, text="Password: ", font=("bold", 16)).grid(row=1, sticky='e')
        self.entry_username = tk.Entry(self, font=("bold", 14))
        self.entry_password = tk.Entry(self, show="*", font=("bold", 14))
        self.entry_username.grid(row=0, column=1)
        self.entry_password.grid(row=1, column=1)
        tk.Button(self, text="Login", font=("bold", 10), command=self.master._login_btn_clicked).grid(columnspan=2)


class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("test")
        self.minsize(950, 450)
        self.login_frame = Login()
        self.login_frame.pack()

    def _login_btn_clicked(self):
        username = self.login_frame.entry_username.get()
        password = self.login_frame.entry_password.get()
        account_list = [line.split(":", maxsplit=1) for line in open("passwords.txt")]
        accounts = {key: value.rstrip() for key, value in account_list}
        if accounts[username] == password:
            self.login_frame.destroy()
            NoteFrame = NotebookFrame(username)
            NoteFrame.pack()
        else:
            print("error")


if __name__ == "__main__":
    App().mainloop()
Mike - SMT
  • 14,784
  • 4
  • 35
  • 79
  • keep seeing this `if __name__ == "__main__:` what is this? –  Sep 27 '19 at 15:03
  • @HecticPython here is a post that answers just that question. [What does if __name__ == “__main__”: do?](https://stackoverflow.com/questions/419163/what-does-if-name-main-do). – Mike - SMT Sep 27 '19 at 15:15