Hi i am trying to create a password manager with the intention of helping myself learn python and tkinter and sqlite3 however i have ran into a problem,everytime i create a new password i want a button to appear showing that passwordname and then the user could click on it to access their actual password.I have attempted to do this via a for loop however while it loops through every password in my database it does not generate my button.Any help would be greatly appreciated.Thank you in advance here is my code(the for loop is between lines 89 and 92).
import sqlite3
from tkinter import *
from tkinter import messagebox
#creating database
conn=sqlite3.connect("Passwords.db")
cursor=conn.cursor()
#creating table-num of quotation is number of lines,name of field then datatype e.g passwordNameoutofdatabase text
cursor.execute("""create table IF NOT EXISTS Passwords
(passwordName text PRIMARY KEY
,UserName text
,password text
)""")#inside are columns/categorys
#login window
login=Tk()
login.title("Password Manager")
login.geometry("1366x768")
screen_width=login.winfo_screenwidth()#gets screen width
screen_height=login.winfo_screenheight()#gets screen height
loginBox=Entry(login,width=100)
loginBox.pack()
def loginClick():
if loginBox.get()=="steve":
#main window
# creating main password screen window
main = Toplevel()
main.title("Password Manager")
main.geometry("1366x768")
screen_width = main.winfo_screenwidth() # gets screen width
screen_height = main.winfo_screenheight() # gets screen height
# setting background
canvas = Canvas(main, width=screen_width, height=screen_height)
canvas.config(bg="white")
canvas.pack()
# creating lines
canvas.create_line(200, 0, 200, screen_height, fill="blue", width=25)
canvas.create_line(0, 100, screen_width, 100, fill="blue",
width=25) # x,y,x1,y1 warning grid system is weird lower y is higher
# creating labels
passwordLabel = Label(main, bg="white", text="Passwords",
font=("freesans", 20)) # set window then text then font then size
passwordLabel.place(x=50, y=50)
# commands for buttons
def newPasswordclick():
# creating Labels for search bars and title
newPasswordlabel = Label(main, text="Create Password Screen", bg="white", font=("freesans", 20))
newPasswordlabel.place(x=215, y=50)
def nameEntry():
passwordNameoutofdatabase = NameofPassword.get()
username = Name.get()
password = Password.get() # gets input from the input box
cursor.execute("""SELECT passwordName
FROM Passwords
WHERE passwordName=?
""",
(passwordNameoutofdatabase,))#selects passwordName1 from table then Selects Where column = passwordNameoutofdatabase/any variable as variables by question marks in sqlite3
primaryKeyCheck=cursor.fetchone()
print(primaryKeyCheck)
#Insert passwordNameoutofdatabase,Username,password
if primaryKeyCheck!=None:
NameofPassword.delete(0, END) # deletes text within the range of 0 to end
Name.delete(0, END)
Password.delete(0, END)
messagebox.showerror(title="ERROR",message="Already have a password with this name")
else:
NameofPassword.delete(0, END) # deletes text within the range of 0 to end
Name.delete(0, END)
Password.delete(0, END)
cursor.execute("INSERT INTO Passwords (passwordName,Username,password )VALUES(?,?,?)",(passwordNameoutofdatabase,username,password,))#Inserts variables into table by referencing which variables correspond to each column
conn.commit()
cursor.execute("SELECT*FROM Passwords")#Selects Passwords table
Data=cursor.fetchall()#fetches everything selected
cursor.execute("SELECT passwordName FROM Passwords")#selects password name from table
passwordNames=cursor.execute("Select passwordName FROM Passwords")
Passwords=cursor.execute("SELECT* FROM Passwords")
for passwordNames in Passwords:
Button(main,text=(str(passwordNames)),font=("freesans",20))
print("steve")
cursor.close()#closes database
print(Data)#prints everything fetched
if passwordNameoutofdatabase != "" and username != "" and password != "": # checks that the user has typed in all the input boxes
NameofPassword.destroy() # destroy destroys labels and other widgets
Name.destroy()
Password.destroy()
UserNameLabel.destroy()
nameEnter.destroy()
newPasswordlabel.destroy()
NameofPasswordlabel.destroy()
PasswordLabel.destroy()
# labels for buttons
NameofPasswordlabel = Label(main, text="Enter the name of your password", bg="white", font=("freesans", 10))
NameofPasswordlabel.place(x=215, y=125)
UserNameLabel = Label(main, text="Enter your username or email address", bg="white", font=("freesans", 10))
UserNameLabel.place(x=215, y=175)
PasswordLabel = Label(main, text="Enter your password", bg="white", font=("freesans", 10))
PasswordLabel.place(x=215, y=225)
# creating search bars
NameofPassword = Entry(main, width=100, highlightthickness=2, highlightbackground="black",
highlightcolor="black")
NameofPassword.place(x=215, y=150)
Name = Entry(main, width=100, highlightthickness=2, highlightbackground="black",
highlightcolor="black") # highlight attributes create border
Name.place(x=215, y=200)
Password = Entry(main, width=100, highlightthickness=2, highlightbackground="black", highlightcolor="black")
Password.place(x=215, y=250)
# buttons
nameEnter = Button(main, text="Enter", command=nameEntry)
nameEnter.place(x=850, y=250)
# creating buttons
NewPasswordImg = PhotoImage(file="C:\VsCode\Password Manager\Create Password Button.png")
newPassword = Button(main, image=NewPasswordImg, compound="center", text="Create new password",command=newPasswordclick) # to combine text with image need to set compound to center,left or right which determines where text is put
newPassword.config(height=50, width=150)
newPassword.place(x=20, y=125)
main.mainloop()
loginButton=Button(login,text="Login",font=("freesans",20),command=loginClick,width=5,height=10)
loginButton.pack()
login.mainloop()
CodePudding user response:
As you are trying to improve your skills on Python, I recommend you to use classes, which are very useful when manipulating UI like windows on tkinter.
As for your problem with buttons not being generated, you could try putting them in a list.
I tried to do something with passwords and usernames, appearing on a window with some buttons. The approach is different, but it may give you some ideas for your project.
#!/usr/bin/python3
import tkinter as tk
CONNECT_APP_DIMENSIONS=("400", "200")
PASSWORD_APP_DIMENSIONS=("800", "500")
USERNAME_PASSWORD_IN_DB=[
['banane_user', 'banane_password'],
['kiwi_user', 'kiwi_password'],
['patate_user', 'patate_password'],
]
class PasswordApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.wm_geometry(PASSWORD_APP_DIMENSIONS[0] "x" PASSWORD_APP_DIMENSIONS[1])
# ---- ADDING GESTION ----
# username entry
self.username_entry=tk.Entry(self, width=20)
self.username_entry.focus_set()
self.username_entry.insert(tk.END, "new_username")
self.username_entry.grid(row=0,column=0)
# password entry
self.password_entry=tk.Entry(self, width=20)
self.password_entry.focus_set()
self.password_entry.insert(tk.END, "new_password")
self.password_entry.grid(row=0,column=1)
# add username/password button
self.add_button = tk.Button(self, text="add", command=self.add_account)
self.add_button.grid(row=0,column=2)
# status label
self.status_text=tk.StringVar(self)
self.status = tk.Label(self, textvariable=self.status_text)
self.status.grid(row=0,column=3)
# ---- END ADDING GESTION ----
# intiliaze some list
self.display_buttons=[]
self.password_status_texts=[]
self.password_labels=[]
# make a copy of DB
self.database = USERNAME_PASSWORD_IN_DB.copy()
# display username/password list
self.refresh_list()
def refresh_list(self):
cpt_row = 1
simple_cpt = 0
for username_password in self.database:
# new password was added
if simple_cpt < len(self.display_buttons):
cpt_row = 1
simple_cpt = 1
continue
# display password button
self.display_buttons.append(
tk.Button(
self,
text=username_password[0],
command= lambda simple_cpt=simple_cpt: self.display_password(db_id=simple_cpt)
)
)
self.display_buttons[simple_cpt].grid(row=cpt_row,column=0)
# status label
self.password_status_texts.append(tk.StringVar(self, '******'))
self.password_labels.append(tk.Label(self, textvariable=self.password_status_texts[simple_cpt]))
self.password_labels[simple_cpt].grid(row=cpt_row,column=1)
cpt_row = 1
simple_cpt = 1
def display_password(self, db_id):
# updating label associated to username
self.password_status_texts[db_id].set(self.database[db_id][1])
def add_account(self):
# getting user inputs
username=self.username_entry.get()
password=self.password_entry.get()
# check minimum size
if len(username) < 4 or len(password) < 4:
self.status_text.set("Incorrect username/password")
return
# check username not already in self.database
for username_password in self.database:
if username_password[0] == username:
self.status_text.set("Username already in DB")
return
# adding username/password to DB
self.database.append([username, password])
# refreshing list
self.refresh_list()
class ConnectionApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.wm_geometry(CONNECT_APP_DIMENSIONS[0] "x" CONNECT_APP_DIMENSIONS[1])
# username entry
self.entry=tk.Entry(self, width=20)
self.entry.focus_set()
self.entry.insert(tk.END, "username")
self.entry.grid(row=0,column=0)
# connect button
self.connect_button = tk.Button(text="connect", command=self.connect)
self.connect_button.grid(row=0,column=1)
# status label
self.status_text=tk.StringVar()
self.status = tk.Label(textvariable=self.status_text)
self.status.grid(row=0,column=2)
def connect(self):
if self.entry.get() == "steve":
self.status_text.set("Connected")
self.password_app=PasswordApp()
self.destroy()
else:
self.status_text.set("Unknown user")
if __name__ == '__main__':
connect_app=ConnectionApp()
connect_app.mainloop()