Im trying to display the variable that was in my login class to my menu class but whenever I do so I always get the error Object login has no attribute user.
Here is my login.py file
def login(self):
global con
user = self.txt_user.get().strip()
pwd = self.txt_pass.get().strip()
if user == "" or pwd == "":
messagebox.showerror("Error", "Please fill up all fields!")
else:
try :
con=pymysql.connect(host="localhost",user="root",password="",database="employee")
cur=con.cursor()
cur.execute("select 1 from employeelist where username=%s and password=%s", (user,pwd))
if cur.rowcount == 1:
messagebox.showinfo("Success", "Login Successful", parent=self.root)
self.menu()
else:
messagebox.showerror("Error", "Wrong Username or Password. Please try again!")
except Exception as ex:
messagebox.showerror("Error",f"Error due to: {str(ex)}",parent=self.root)
finally:
con.close()
def menu(self):
self.root.destroy()
menu.MenuForm()
if __name__ == "__main__":
root = Tk()
obj = Login(root)
root.mainloop()
Here is my menu.py file
from tkinter import *
from tkinter import ttk, messagebox
import PIL
from PIL import ImageTk
from PIL import Image
import login
class Menu:
def __init__(self,root):
self.root = root
self.root.title("Main Menu")
self.root.geometry("1350x768+0+0")
self.root.resizable(False, False)
self.bg = ImageTk.PhotoImage(file="Images/bgimage.jpg")
bg = Label(self.root, image=self.bg).place(x=0, y=0, relwidth=1, relheight=1)
framemenu = Frame(self.root, bg="white")
framemenu.place(x=350, y=100, height=500, width=700)
welcometitle = Label(framemenu, text="Welcome " + login.Login.user(), font=("Arial", 30, "bold"), fg="orange", bg="white").place(x=70,y=70)
def MenuForm():
win = Tk()
obj = Menu(win)
if __name__ == "__main__":
root = Tk()
obj = Menu(root)
root.mainloop()
I have imported login in my menu class but it still gives me the error object has no instance.
You can follow #Hosseinreza's approach to improve your code but if you want to work with your existing code then pass the user attribute to the menu class like below code excerpts
def login(self)
if cur.rowcount == 1:
messagebox.showinfo("Success", "Login Successful", parent=self.root)
self.menu(user)
def menu(self, user):
self.root.destroy()
menu.MenuForm(user)
then in Menu class, you can use it as below:
from tkinter import *
from tkinter import ttk, messagebox
import PIL
from PIL import ImageTk
from PIL import Image
class Menu:
def __init__(self,root, user):
self.root = root
self.root.title("Main Menu")
self.root.geometry("1350x768+0+0")
self.root.resizable(False, False)
self.bg = ImageTk.PhotoImage(file="Images/bgimage.jpg")
bg = Label(self.root, image=self.bg).place(x=0, y=0, relwidth=1, relheight=1)
framemenu = Frame(self.root, bg="white")
framemenu.place(x=350, y=100, height=500, width=700)
welcometitle = Label(framemenu, text="Welcome " + user, font=("Arial", 30, "bold"), fg="orange", bg="white").place(x=70,y=70)
def MenuForm(user):
win = Tk()
obj = Menu(win, user)
if __name__ == "__main__":
root = Tk()
obj = Menu(root)
root.mainloop()
Better pass the user to menu.MenuForm() via argument instead:
class Login:
...
def login(self):
user = self.txt_user.get().strip()
pwd = self.txt_pass.get().strip()
if user == "" or pwd == "":
messagebox.showerror("Error", "Please fill up all fields!")
else:
try :
con=pymysql.connect(host="localhost",user="root",password="",database="employee")
cur=con.cursor()
cur.execute("select 1 from employeelist where username=%s and password=%s", (user,pwd))
if cur.rowcount == 1:
messagebox.showinfo("Success", "Login Successful", parent=self.root)
self.menu(user) # pass user to self.menu()
else:
messagebox.showerror("Error", "Wrong Username or Password. Please try again!")
except Exception as ex:
messagebox.showerror("Error",f"Error due to: {str(ex)}",parent=self.root)
finally:
con.close()
def menu(self, user):
self.root.destroy()
menu.MenuForm(user) # pass user to menu.MenuForm()
menu.py:
from tkinter import *
#from tkinter import ttk, messagebox
from PIL import Image, ImageTk
class Menu:
def __init__(self, root, user): # user passed as argument
self.root = root
self.root.title("Main Menu")
self.root.geometry("1350x768+0+0")
self.root.resizable(False, False)
self.bg = ImageTk.PhotoImage(file="Images/bgimage.jpg")
bg = Label(self.root, image=self.bg).place(x=0, y=0, relwidth=1, relheight=1)
framemenu = Frame(self.root, bg="white")
framemenu.place(x=350, y=100, height=500, width=700)
welcometitle = Label(framemenu, text="Welcome " + user, font=("Arial", 30, "bold"), fg="orange", bg="white").place(x=70,y=70)
def MenuForm(user): # user passed as argument
win = Tk()
obj = Menu(win, user) # pass user to `Menu` class
if __name__ == "__main__":
root = Tk()
obj = Menu(root, "user")
root.mainloop()
Importing is not enough.
When you are working with objects , if you wanna use an object first of all you have to make an instance then you can work with the instance , here's an example:
class login():
def __init__(self):
print("Hi im Login Object")
class main():
def __init__(self):
login_obj = login() # Instance created
main()
As you see I made an instance of class Login into main class then it Worked.
Output:
Hi im Login Object
Related
I have trouble with Tkinter to open a new window(from another module).
In Log.py module we have the code to catch the Name
and Id from the User.
Entered data is sent to db.py and checked.
If the User Name and Id exist in the DB db.py, it will return True
to Log.py module and with the result from the callback function will open the test_win.py.
My trouble is in 3. (1. and 2. have been tested and without 3. and they work well).
When I added the function that if the result from the callback function is True, it does not work as expected.
When I run the script with def open_inventory it opens first the test_win.py and once done, it closes test_win.py and opens Log.py when it should be the oposite.
Appreciate any suggestions/answers to fix the above issue.
Log.py
import tkinter as tk
from tkinter import ttk, messagebox
from _userDB import *
import test_win
db = UserDb()
class Login:
def __init__(self, window):
self.window = window
self.window.geometry("300x300")
self.window.title("Inventory")
self.window.eval("tk::PlaceWindow . center")
title1 = ttk.Label(window, text=f"Inventory\n", font=('helvetica', 18, 'bold'))
title1.pack()
subtitle1 = ttk.Label(window, text=f"Log in\n", font=('helvetica', 16, 'bold'))
subtitle1.pack()
login_name = ttk.Label(window, text=f"Name: ", font=('helvetica', 12, 'bold'))
login_name.pack(anchor='center')
self.log_name_entry = ttk.Entry()
self.log_name_entry.pack()
login_id = ttk.Label(window, text=f"ID:", font=('helvetica', 12, 'bold'))
login_id.pack()
self.log_id_entry = ttk.Entry()
self.log_id_entry.pack()
enter_btn = tk.Button(window, text=f"Log in", font=('Helvetica', 14, 'bold'), bg='#A9A9A9', cursor="hand2",
activebackground="#696969",
command=lambda: self.check())
enter_btn.pack(pady=15)
# here send data to the db.py module to check in the DB if the User name and id exist
def check(self):
user_name = self.log_name_entry.get()
user_id = self.log_id_entry.get()
print(user_name, user_id)
if user_name == "" and user_id == "" or user_name == "" or user_id == "":
messagebox.showwarning("ERROR", 'All tha cases most be filling')
else:
db.user_check(user_name, user_id, self.open_inventory())
# If result from db.py is True open the new window(test_win.py)
def open_inventory(self, result):
if result:
ne_win = tkinter.Toplevel(self.window)
win = test_win(ne_win)
else:
print("Data does not exist")
messagebox.showerror("ERROR", f'The user name or the id no exist \n Try again!')
def page():
window = tk.Tk()
Login(window)
window.mainloop()
if __name__ == '__main__':
page()
Test.py
from tkinter import Label, Toplevel
win = Toplevel()
win.geometry("300x300")
win.title("new window")
label1 = Label(win, text='Welcome')
label1.pack()
I am trying to create a main screen that changes to a homepage after user logged in. If I change while loop it never prints or opens login page. Now I changed it but whenever i logged in the login def returns true but main.py keeps it as False.
main.py:
from tkinter import *
from login import LoginNP
class NP:
def __init__(self, root):
self.root = root
self.root.geometry("1350x700+0+0")
self.root.title("New Project")
self.buton = Button(text="Giriş yap", command=self.loginPage).pack(anchor=NE)
self.title_frame = Frame(borderwidth=5,height=150,width=300, relief=RIDGE)
self.title_frame.pack(anchor=N)
self.welcome_label = Label(self.title_frame, text="Hello", height=10, width=10).pack(padx=10, pady=5)
while True:
root.update_idletasks()
root.update()
if not self.checkLogin():
break
else:
pass
def checkLogin(self):
if LoginNP.loginMessage:
print("A")
return True
else:
print("B")
return False
def loginPage(self):
self.new_win = Toplevel(self.root)
self.new_obj = LoginNP(self.new_win)
self.new_win.attributes('-topmost', True)
class HomePage:
def __init__(self, root):
self.root = root
self.root.geometry("1350x700+0+0")
self.root.title("Homepage")
self.title_frame = Frame(self.root, height=500, width=300)
self.title_frame.pack(anchor=CENTER, padx=10, pady=5)
self.welcome_label = Label(self.title_frame, text="Homepage", height=10, width=10).pack(padx=10, pady=5)
if __name__ =="__main__":
root=Tk()
obj=NP(root)
root.mainloop()
I want to update my NP window with Homepage window but in while loop program not getting result from login.py
login.py:
from tkinter import *
import sqlite3
from tkinter import messagebox
con = sqlite3.connect("npdb.db")
cur = con.cursor()
class LoginNP:
def __init__(self, root):
self.root = root
self.root.geometry("350x240")
self.root.title("Login Page")
#vars
self.username_var = StringVar()
self.password_var = StringVar()
#frames
self.upper_frame = Frame(self.root, height=70)
self.upper_frame.pack(anchor=N, fill=X, padx=10, pady=5)
self.middle_frame = Frame(self.root, height=70)
self.middle_frame.pack(anchor=CENTER, fill=X, padx=10, pady=5)
self.lower_frame = Frame(self.root, height=70)
self.lower_frame.pack(anchor=S, fill=X, padx=10, pady=5)
#label&entry
self.username_label = Label(self.upper_frame, text="Username: ").pack(anchor=W, padx=10, pady=5)
self.username_entry = Entry(self.upper_frame, textvariable=self.username_var).pack(anchor=W, padx=10, pady=5, fill=X)
self.password_label = Label(self.middle_frame, text="Password: ").pack(anchor=W, padx=10, pady=5)
self.password_entry = Entry(self.middle_frame, textvariable=self.password_var, show="*").pack(anchor=W, padx=10, pady=5, fill=X)
self.login_btn = Button(self.lower_frame, text="Login", command=self.loginMessage).grid(column=0, row=0, padx=10, pady=5)
self.register_btn = Button(self.lower_frame, text="Register",command=self.register).grid(column=1, row=0, padx=205, pady=5)
#property
def login(self):
with con:
cur.execute("SELECT * FROM user_database WHERE username=:username", {'username': self.username_var.get()})
if cur.fetchone() == None:
return False
else:
cur.execute("SELECT password FROM user_database WHERE username=:username", {'username': self.username_var.get()})
`enter code here` row = cur.fetchone()
return row[0] == self.password_var.get()
def loginMessage(self):
if self.login:
messagebox.showerror(title="Approve!", message="Giriş Başarılı!")
else:
messagebox.showerror(title="Deny!", message="Kullanıcı adı veya şifre hatalı!")
self.root.destroy()
return self.login
def search(self):
with con:
cur.execute("SELECT * FROM user_database WHERE username=:username", {'username': self.username_var.get()})
return len(cur.fetchall()) < 1
def register(self):
if self.username_var.get().strip() == "" or self.password_var.get().strip() == "":
messagebox.showerror(title='Hata!', message="Lütfen boşluk bırakmayınız!")
else:
if not self.search():
messagebox.showerror(title='Hata!', message="Kullanıcı adı zaten kayıtlı.\nLütfen başka bir kullanıcı adı alınız.")
else:
cur.execute("""INSERT INTO user_database VALUES (?, ?)""", (self.username_var.get(), self.password_var.get()))
con.commit()
if __name__ =="__main__":
root=Tk()
obj=LoginNP(root)
root.mainloop()
I suspect that if LoginNP.loginMessage: in checkLogin doesn't do what you think it does.
You have imported the LoginNP class, and loginMessage is a method of this class.
So, if LoginNP.loginMessage: basically means "does the class LoginNP have a method loginMessage". To which the answer is True.
But you are not instantiating an object of type LoginNP nor calling a method on that instance.
Check this example:
In [1]: class Foo:
...: def __init__():
...: pass
...: def bar():
...: print("calling 'bar'")
...:
In [2]: if Foo.bar:
...: print(True)
...:
True
And note the absence of the printed message calling 'bar'.
I want a placeholder entry that is done by the below code. but I need the input password which would be hidden from the user (which may be in the form of asterisks.)
from tkinter import *
root=Tk()
root.geometry("300x200+600+250")
root.config(background="#E0FFFF")
root.resizable(False,False)
def userText(event):
e1.delete(0,END)
usercheck=True
def passText(event):
e2.delete(0, END)
passcheck=True
a=StringVar()
b=StringVar()
usercheck=False
passcheck=False
Label(root,text="User name",bg="#E0FFFF").place(x=20,y=50)
e1= Entry(root,textvariable=a)
e1.place(x=100,y=50)
e1.insert(0,"Enter username")
e1.bind("<Button>",userText)
Label(root,text="Password",bg="#E0FFFF").place(x=20,y=95)
e2= Entry(root,textvariable=b)
e2.place(x=100,y=95)
e2.insert(0,"Enter password")
e2.bind("<Button>",passText)
root.mainloop()
Extended tkinter.Entry showing placeholder text and * on a password entry.
Live-Demo
import tkinter as tk
class Entry(tk.Entry):
def __init__(self, master, placeholder):
super().__init__(master)
self.placeholder = placeholder
self._is_password = True if placeholder == "password" else False
self.bind("<FocusIn>", self.on_focus_in)
self.bind("<FocusOut>", self.on_focus_out)
self._state = 'placeholder'
self.insert(0, self.placeholder)
def on_focus_in(self, event):
if self._is_password:
self.configure(show='*')
if self._state == 'placeholder':
self._state = ''
self.delete('0', 'end')
def on_focus_out(self, event):
if not self.get():
if self._is_password:
self.configure(show='')
self._state = 'placeholder'
self.insert(0, self.placeholder)
Usage:
if __name__ == "__main__":
root = tk.Tk()
username = Entry(root, "username")
username.pack()
password = Entry(root, "password")
password.pack()
root.mainloop()
to hide the password use:
e2.config(show='*')
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()
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()
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.
I'm trying to make a login gui using tkinter, and I want a new window to open when I click on change password.
When the window opens it should prompt the user for a new password, and then change and store the password. Afterwards, it should login again using the changed password.
import tkinter as tk
import tkinter.messagebox as tm
class LoginFrame(tk.Frame):
storedPassword='password'
def __init__(self, master):
super().__init__(master)
#storedPassword='password'
self.label_username = tk.Label(self, text="Username")
self.label_password = tk.Label(self, text="Password")
self.entry_username = tk.Entry(self)
self.entry_password = tk.Entry(self)#, show="*") to help us see new password
self.label_username.grid(row=0)
self.label_password.grid(row=1)
self.entry_username.grid(row=0, column=1)
self.entry_password.grid(row=1, column=1)
self.logbtn = tk.Button(self, text="Login", command=self._login_btn_clicked)
self.logbtn.grid(columnspan=2)
newPassword = self.entry_password.get()
print(newPassword)
self.logbtn = tk.Button(self, text="change_password", command=self.change_password)
self.logbtn.grid(columnspan=2)
def change_password(self,newPassword):
self.new_password = tk.Label(self, text="new password")
self.entry_newpassword = tk.Entry(self)
self.storedPassword=newPassword
print(self.entry_newpassword.get())
def _login_btn_clicked(self):
username = self.entry_username.get()
password = self.entry_password.get()
if username == "admin":
if password == self.storedPassword:
tm.showinfo("Login info", "Welcome admin")
self.storedPassword=self.entry_password.get()
else:
tm.showerror("Login error", "Incorrect password")
else:
tm.showerror("Login error", "Incorrect username")
window= tk.Tk()
lf = LoginFrame(window)
#root = tk.Tk()
#newWindow= LoginFrame(root)
#root.mainloop()
window.mainloop()
Simply destroy the initial window first using window.destroy() and then create a new window in a function when it is called by the button. Continue adding entry widgets and labels as you know and get the new password and run another function to go back to initial page after using root.destroy() to remove change password window.
Here is a simple code showing what I just said:
from tkinter import *
from tkinter import messagebox
storedPassword = 'password'
def loginok(username,password):
global storedPassword
if username == "admin":
if password == storedPassword:
messagebox.showinfo("Login Successful!","Welcome Admin")
else:
messagebox.showerror("Login Failed!","Wrong Password")
else:
messagebox.showerror("Login Failed!","Wrong Username")
def cpass():
global window
window.destroy()
window = Tk()
Label(window,text="Enter new password:").pack()
passn = Entry(window,width=15)
passn.pack()
Button(window,text="OK",command=lambda:chgpass(passn.get())).pack()
window.mainloop()
def chgpass(newpass):
global window
global storedPassword
storedPassword = newpass
window.destroy()
login()
def login():
global window
window = Tk()
Label(window,text="Username:").pack()
usern = Entry(window,width=15)
usern.pack()
Label(window,text="Password:").pack()
passw = Entry(window,width=15,show="*")
passw.pack()
Button(window,text="Login",command=lambda:loginok(usern.get(),passw.get())).pack()
Button(window,text="Forgot",command=cpass).pack()
window.mainloop()
login()