I'm making a program to login or register an account. But when I tried to read a text file to check for the username and password, file.read() returned nothing for some reason.
Here is the code:
def login_incorrect():
Label(loginPage, text='Username or password incorrect.').place(x=120, y=120)
def LoginToAccount():
with open('AccountDatabase.txt', 'r'):
if loginUsernameE.get() + '.' + loginPasswordE.get() not in open('AccountDatabase.txt').read():
login_incorrect()
else:
print('Logged in!')
This program will always give me the 'password incorrect' message, because open('AccountDatabase.txt', 'r'): always returns a blank line.
Here is my full code:
from tkinter import *
import time
root = Tk()
root.title("Account Signup")
DarkBlue = "#2460A7"
LightBlue = "#B3C7D6"
root.geometry('350x230')
LoggedIn = False
Menu = Frame()
loginPage = Frame()
registerPage = Frame()
for AllFrames in (Menu, loginPage, registerPage):
AllFrames.place(relwidth=1, relheight=1) # w/h relative to size of master
AllFrames.configure(bg=LightBlue)
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
def show_frame(frame):
frame.tkraise()
show_frame(Menu)
def login_incorrect():
Label(loginPage, text='Username or password incorrect.').place(x=120, y=120)
def LoginToAccount():
with open('AccountDatabase.txt', 'r'):
if loginUsernameE.get() + '.' + loginPasswordE.get() not in open('AccountDatabase.txt').read():
login_incorrect()
else:
print('Logged in!')
def CreateNewAccount():
print('create new account')
while True: # This loop will run as long as the new account hasn't been created.
with open('AccountDatabase.txt'):
if len(newUsernameE.get()) < 4:
lenError = Label(text='Username must be 4 characters or more.')
print('4')
lenError.place(x=120, y=120)
if newUsernameE.get() + "." in open('AccountDatabase.txt').read():
print('username taken')
# newUsername = input("Sorry, this username is already taken. Please choose another username:")
continue
if newUsernameE.get() + '.' not in open('AccountDatabase.txt').read():
print('create pass')
AccountDatabase.write(newUsernameE.get() + "." + newPasswordE.get() + "\n")
break
# ============= Menu Page =========
menuTitle = Label(Menu, text="Menu", font=("Arial", 25), bg=LightBlue)
menuTitle.place(x=130, y=25)
loginMenuButton = Button(Menu, width=25, text="Login", command=lambda: show_frame(loginPage))
loginMenuButton.place(x=85, y=85)
registerMenuButton = Button(Menu, width=25, text="Register", command=lambda: show_frame(registerPage))
registerMenuButton.place(x=85, y=115)
# ======== Login Page ===========
loginUsernameL = Label(loginPage, text='Username')
loginUsernameL.place(x=30, y=60)
loginUsernameE = Entry(loginPage)
loginUsernameE.place(x=120, y=60)
loginPasswordL = Label(loginPage, text='Password')
loginPasswordL.place(x=30, y=90)
loginPasswordE = Entry(loginPage)
loginPasswordE.place(x=120, y=90)
backButton1 = Button(loginPage, text='Back', command=lambda: show_frame(Menu))
backButton1.place(x=0, y=0)
loginButton = Button(loginPage, text='Login', width=20, command=LoginToAccount)
loginButton.place(x=100, y=150)
# ======== Register Page ===========
newUsernameL = Label(registerPage, text='New Username')
newUsernameL.place(x=43, y=60)
newUsernameE = Entry(registerPage)
newUsernameE.place(x=140, y=60)
newPasswordL = Label(registerPage, text='New Password')
newPasswordL.place(x=45, y=90)
newPasswordE = Entry(registerPage)
newPasswordE.place(x=140, y=90)
confirmPasswordL = Label(registerPage, text='Confirm Password')
confirmPasswordL.place(x=25, y=120)
confirmPasswordE = Entry(registerPage)
confirmPasswordE.place(x=140, y=120)
backButton2 = Button(registerPage, text='Back', command=lambda: show_frame(Menu))
backButton2.place(x=0, y=0)
registerButton = Button(registerPage, text='Login', width=20, command=CreateNewAccount)
registerButton.place(x=100, y=180)
root.mainloop()
replace this
with open('AccountDatabase.txt', 'r'):
if loginUsernameE.get() + '.' + loginPasswordE.get() not in open('AccountDatabase.txt').read():
to
with open('AccountDatabase.txt', 'r') as f:
if loginUsernameE.get() + '.' + loginPasswordE.get() not in f.read():
login_incorrect()
else:
print('Logged in!')
def LoginToAccount():
with open('AccountDatabase.txt', 'r') as f:
if loginUsernameE.get() + '.' + loginPasswordE.get() not in f.read():
login_incorrect()
else:
print('Logged in!')
and here we open the file in append and in read mode we read the file and make sure that the user isn't already there and append the new user.password if the user isn't in the database
def CreateNewAccount():
print('create new account')
while True: # This loop will run as long as the new account hasn't been created.
with open('AccountDatabase.txt', 'r') as fr, open('AccountDatabase.txt', 'a') as fa:
if len(newUsernameE.get()) < 4:
lenError = Label(text='Username must be 4 characters or more.')
print('4')
lenError.place(x=120, y=120)
if newUsernameE.get() + "." in fr.read():
print('username taken')
# newUsername = input("Sorry, this username is already taken. Please choose another username:")
continue
else:
print('create pass')
fa.write(newUsernameE.get() + "." + newPasswordE.get() + "\n")
break
I am writing code to build a basic employee management software with GUI. When I load sample data, I believe they are being created as Class Objects (Employee) because when I debug I can see that all of the arguments are passed and the object is created. HOWEVER, when I try to modify them later (such as hired status), it returns an error 'str' object has no attribute 'hired_status'
Employee Class:
"""Create Employee class so all employees can be Employee Objects"""
def __init__(self, fname='', lname='', phone='', email='', job='', interview_rating=0, hired_status='N'):
self.first = fname
self.last = lname
self.phone_number = phone
self.email_address = email
self.interview = interview_rating
self.__emp_job = job
self.hired_status = hired_status
#property
def first_name(self):
return self.__first
#first_name.setter
def first_name(self, fname):
if fname.isalpha() and len(fname) >= 1:
self.__first = fname.capitalize()
else:
self.__first = 'Unknown'
#property
def last_name(self):
return self.__last
#last_name.setter
def last_name(self, lname):
if lname.isalpha() and len(lname) >= 1:
self.__last = lname.capitalize()
else:
self.__last = 'Unknown'
#property
def email_address(self):
return self.__email_address
#email_address.setter
def email_address(self, email):
if len(email) >=1 and '#' in email:
self.__email_address = email
else:
self.__email_address = 'Unknown'
#property
def phone_number(self):
return self.__phone_number.format(str)
#phone_number.setter
def phone_number(self, phone):
if len(phone) >= 1:
self.__phone_number = phone
else:
self.__phone_number = 'Unknown'
#property
def job(self):
return self.__emp_job
#job.setter
def job(self, job):
self.__emp_job = job
#property
def hired_status(self):
return self.__hired_status
#hired_status.setter
def hired_status(self, hired):
self.__hired_status = hired
def __str__(self):
return f'{self.first_name},{self.last_name},{self.phone_number},{self.email_address},{self.job},' \
f'{self.hired_status}'
Main Class:
def load_employees():
"""
Loads same employees from the text file.
- Creates an Employee object for each employee listed in the file.
- Retrieves comma-separated values from each line and assigns it to the corresponding arg in Employee()
- Adds the new employee object to the list of current employees.
- Displays the employees on the screen for the user.
"""
global first_name, last_name, phone, email, job, new_employee, current_employees, hired_status
current_employees = []
with open('employees.txt', 'r') as file:
for f in file:
first_name, last_name, phone, email, job, hired_status = f.split(',')
sample_employee = Employee(first_name, last_name, phone, email, job, hired_status)
sample_employee.first_name = first_name
sample_employee.last_name = last_name
sample_employee.phone_number = phone
sample_employee.email_address = email
sample_employee.job = job
sample_employee.hired_status = hired_status
current_employees.append(f)
emp_list.insert(END, f)
Trying to hire
def hire_candidate():
global first_name, last_name, phone, email, job, new_employee, current_employees, edit_mode, hired_status, emp_list
new_employee = emp_list.get(ANCHOR)
new_employee.hired_status = 'Y'
adding new employee with the GUI
def save_new_employee():
"""
When user clicks "Save Employee" the program will create or edit an Employee object.
- A new Employee will be added to the list of current employees and appear in the GUI.
- If editing, the Employee object will be updated with the new information.
- The user is prompted with a message saying they have added or updated an Employee.
- The Employee Management form will then clear all textboxes.
"""
global first_name, last_name, phone, email, job, new_employee, current_employees, edit_mode, hired_status
global applicant_first_tbx, applicant_last_tbx, applicant_phone_tbx, applicant_email_tbx, jobs_cbx
new_employee = None
new_employee = Employee(first_name, last_name, phone, email, job, hired_status)
new_employee.first_name = applicant_first_tbx.get()
new_employee.last_name = applicant_last_tbx.get()
new_employee.phone_number = applicant_phone_tbx.get()
new_employee.email_address = applicant_email_tbx.get()
new_employee.job = job
if edit_mode:
x = emp_list.curselection()
current_employees[edit_index] = x
emp_list.delete(x)
emp_list.insert(edit_index, new_employee)
current_employees.pop(edit_index)
current_employees.append(new_employee)
edit_mode = False
messagebox.showinfo('Employee Information Updated.', f'Information for {new_employee.first_name} '
f'{new_employee.last_name} has been updated.')
else:
current_employees.append(new_employee)
emp_list.insert(END, new_employee)
messagebox.showinfo('New Employee Added', f'{new_employee.first_name} {new_employee.last_name} '
f'has been added to your roster.')
applicant_first_tbx.delete(0, END)
applicant_last_tbx.delete(0, END)
applicant_phone_tbx.delete(0, END)
applicant_email_tbx.delete(0, END)
Creating the relevant GUI
# create the main program window
win = Tk()
win.title('Employee Management Form')
win.config(bg='skyblue', pady=20, padx=50)
# global variables
current_employees = []
edit_mode = False
first_name = StringVar()
last_name = StringVar()
phone = StringVar()
email = StringVar()
job = StringVar()
hired_status = StringVar()
job_titles = ['Cook', 'Dishwasher', 'Server']
food_handler = ['Yes', 'No']
cook_certs = {1: 'Basic', 2: 'Advanced'}
interview_scores = [1, 2, 3, 4, 5]
y_offset = 10
color = 'skyblue'
new_employee = None
edit_index = 0
employeeManagement = True
# options menu
menu_bar = Menu(win)
win.config(menu=menu_bar)
win.iconbitmap('emgmt.ico')
# Create a menu bar with required cascades and commands
file_menu = Menu(menu_bar, tearoff=False)
view = Menu(menu_bar, tearoff=False)
menu_bar.add_cascade(label='File', menu=file_menu)
# Saves the information entered into the textboxes as a new employee, or overwrites an employee if editing
file_menu.add_command(label='Save Employee', command=save_new_employee)
# Turns on Edit Mode so user can modify information of an existing employee
file_menu.add_command(label='Edit Employee', command=edit_employee)
# Deletes employee obj from the data structure and removes their name from the GUI
file_menu.add_command(label='Delete Employee', command=delete_employee)
# updates the text file of employees, so upon reopening the program, all changes made previously are reflected
file_menu.add_command(label='Save All Changes', command=save_all_changes)
# Adds the option for the user to switch between employee management and the interview scorecard
menu_bar.add_cascade(label='View', menu=view)
view.add_command(label='Employee Management', command=employee_mgmt)
view.add_command(label='Employee Rating', command=employee_rating)
# frame to display list of current employees. Always visible as per instructions
emp_list_frm = Frame(win, bg='skyblue')
emp_list_frm.pack()
# create the listbox of employees
emp_list_lbl = Label(emp_list_frm, text='Current Employees', bg='systembuttonface', width=30, justify=CENTER)
emp_list_lbl.grid(row=0, column=1, sticky=S)
emp_list = Listbox(emp_list_frm, width=75, listvariable=current_employees)
emp_list.grid(row=1, columnspan=3)
# employee management frame to add, edit, and delete employees
em_frame = Frame(win, bg='skyblue')
em_frame.pack()
# create layout for job application data
applicant_first_lbl = Label(em_frame, text='First Name:', justify=LEFT, pady=y_offset, bg=color)
applicant_first_lbl.grid(row=2, column=0, sticky=W)
applicant_first_tbx = Entry(em_frame, justify=LEFT, width=30, textvariable=first_name)
applicant_first_tbx.grid(row=2, column=1, sticky=W)
applicant_first_tbx.bind('<Key>', name_keys)
applicant_last_lbl = Label(em_frame, text='Last Name:', justify=LEFT, pady=y_offset, bg=color)
applicant_last_lbl.grid(row=3, column=0, sticky=W)
applicant_last_tbx = Entry(em_frame, justify=LEFT, width=30, textvariable=last_name)
applicant_last_tbx.grid(row=3, column=1, sticky=W)
applicant_last_tbx.bind('<Key>', name_keys)
applicant_phone_lbl = Label(em_frame, text='Phone Number:', justify=LEFT, pady=y_offset, bg=color)
applicant_phone_lbl.grid(row=4, column=0, sticky=W)
applicant_phone_tbx = Entry(em_frame, justify=LEFT, width=30, textvariable=phone)
applicant_phone_tbx.grid(row=4, column=1, sticky=W)
applicant_phone_tbx.bind('<Key>', phone_keys)
applicant_email_lbl = Label(em_frame, text='Email:', justify=LEFT, pady=y_offset, bg=color)
applicant_email_lbl.grid(row=5, column=0, sticky=W)
applicant_email_tbx = Entry(em_frame, justify=LEFT, width=30, textvariable=email)
applicant_email_tbx.grid(row=5, column=1, sticky=W)
# create dropdown list for food handlers card
food_handler_label = Label(em_frame, text='Food Handler Card:', justify=LEFT, pady=y_offset, bg=color)
food_handler_label.grid(row=6, column=0, sticky=W)
food_handler_cbx = ttk.Combobox(em_frame, values=food_handler, width=10)
food_handler_cbx.grid(row=7, column=0, sticky=W)
# create dropdown list for applied positions
job_applied_label = Label(em_frame, text='Select Job:', justify=LEFT, pady=y_offset, bg=color)
job_applied_label.grid(row=8, column=0, columnspan=3, sticky=W)
jobs_cbx = ttk.Combobox(em_frame, values=job_titles, width=15)
jobs_cbx.grid(row=9, column=0, sticky=W)
jobs_cbx.bind('<<ComboboxSelected>>', add_job_applied)
# Textbox showing list of all jobs the employee applied for
jobs_applied_txt = Entry(em_frame, justify=LEFT, width=25, textvariable=job_titles)
jobs_applied_txt.grid(row=9, columnspan=2, sticky=E)
# Highest Cook cert
cook_cert_label = Label(em_frame, text='If Cook, select highest certification:', justify=LEFT,
pady=y_offset, bg=color)
cook_cert_label.grid(row=11, column=0, columnspan=3, sticky=W)
# If applying for Cook, Buttons to show the highest level cooking cert
basic_btn = Radiobutton(em_frame, variable=cook_certs, text='Basic', value=1, bg=color, indicatoron=1, state=DISABLED)
basic_btn.grid(row=12, column=0, sticky=W)
advanced_btn = Radiobutton(em_frame, variable=cook_certs, text='Advanced', value=2, bg=color, indicatoron=1, padx=2,
state=DISABLED)
advanced_btn.grid(row=12, column=1, sticky=W)
# Creates a frame for Rating System
rating_frame = Frame(win, bg='skyblue')
rating_lbl = Label(rating_frame, bg=color, text='Interview Rating Form:\n'
'Rate an Employee from 1 to 5, where 1 is the '
'worst and 5 is the best'' in the following categories.')
rating_lbl.grid(row=2, column=0, columnspan=3)
comms_rate_lbl = Label(rating_frame, bg=color, text='1. Verbal/Communication Skills')
comms_rate_lbl.grid(row=3, column=0, sticky=W)
comms_cbx = ttk.Combobox(rating_frame, values=interview_scores, width=10)
comms_cbx.grid(row=4, column=0, sticky=W)
personal_rate_lbl = Label(rating_frame, bg=color, text='2. Interpersonal Skills and Friendliness')
personal_rate_lbl.grid(row=5, column=0, sticky=W)
personal_cbx = ttk.Combobox(rating_frame, values=interview_scores, width=10)
personal_cbx.grid(row=6, column=0, sticky=W)
math_lbl = Label(rating_frame, bg=color, text='3. Math/Problem Solving Skills')
math_lbl.grid(row=7, column=0, sticky=W)
math_cbx = ttk.Combobox(rating_frame, values=interview_scores, width=10)
math_cbx.grid(row=8, column=0, sticky=W)
exp_lbl = Label(rating_frame, bg=color, text='4. Applicable World Experience')
exp_lbl.grid(row=9, column=0, sticky=W)
exp_cbx = ttk.Combobox(rating_frame, values=interview_scores, width=10)
exp_cbx.grid(row=10, column=0, sticky=W)
interview_average_btn = Button(rating_frame, bg='gray', text='Calculate Interview Average',
command=lambda: calculate_interview_average(interview_average_btn))
interview_average_btn.grid(row=11, column=0, columnspan=3, sticky=W, pady=8,)
interview_average_tbx = Entry(rating_frame, bg='white', width=10)
interview_average_tbx.grid(row=11, column=0, sticky=E)
hire_btn = Button(rating_frame, bg='gold', text='Hire Candidate', state=DISABLED, command=hire_candidate)
hire_btn.grid(row=12, column=0, sticky=W)
The idea is that you click and employee form a listbox, then click a button to hire them. I think it is returning the string from the listbox, but I want it to return the object in that location.
Error message
File "C:\Users\Jack\PycharmProjects\Class_Project_jxhawki1\employee_management.py", line 188, in hire_candidate
new_employee.hired_status = 'Y'
AttributeError: 'str' object has no attribute 'hired_status'
There are several problems with the code you have shown. First, your code relies on, in my humble opinion, too many global variables that are not necessary or desirable. Second, while technically all right the way you are mixing grid and pack geometries within the same window will work, it is a dangerous practice. I much prefer sticking with one geometry throughout everything. Finally, I believe your basic problem is that you have provided no data structure to correlate the string value returned from listbox select function to the specific employee instance containing the selected employee's data. The following is not a complete solution to your overall application needs, but does clean up several of the above issues.
First, a rewrite of your Employee class
class Employee:
"""Create Employee class so all employees can be Employee Objects"""
def __init__(self, fname= 'Unknown', lname= 'Unknown', phone= 'Unknown', email= 'Unknown', job= '', interview_rating= 0, hired_status= False):
self._first = None
self._last = None
self._emAdr = None
self._phnNo = None
self._status = False
self._job = None
self._intrvRate = int(interview_rating)
self.first_name = fname
self.last_name = lname
self.phone_number = phone
self.email_address = email
self.employee_job = job
self.hired_status = hired_status
#property
def first_name(self):
return self._first
#first_name.setter
def first_name(self, fname):
try:
if fname.isalpha() and len(fname) >= 1:
self._first = fname.capitalize()
except:
raise ValueError(f"First Name '{fname}' must be alpha and be at least 1 character long")
#property
def last_name(self):
return self._last
#last_name.setter
def last_name(self, lname):
if lname.isalpha() and len(lname) >= 1:
self._last = lname.capitalize()
else:
raise ValueError(f"Last Name '{lname}' must be alpha and be at least 1 character long")
#property
def full_name(self):
return f"{self.last_name}, {self.first_name}"
#property
def email_address(self):
return self._emAdr
#email_address.setter
def email_address(self, email):
if email == '':
self.emAdr = 'Unknown'
elif '#' in email and len(email) >= 1:
self._emAdr = email
else:
raise ValueError(f"Email Address '{email}' must contain an '#' and be at least 1 character long")
#property
def phone_number(self):
return self._phnNo
#phone_number.setter
def phone_number(self, phone):
if len(phone) == 0:
self._phnNo = 'Unknown'
elif len(phone) >= 1:
self._phnNo = phone
else:
raise ValueError(f"Phone Number '{phone}' must be at least 1 character long")
#property
def employee_job(self):
return self._job
#employee_job.setter
def employee_job(self, job):
self._job = job
#property
def hired_status(self):
return self._status
#hired_status.setter
def hired_status(self, status):
if isinstance(status, bool):
self._status = status
else:
raise ValueError(f"Hiring Status '{status}' must be either 'True' or 'False'")
#property
def hire(self):
self.hired_status = True
#property
def fire(self):
self.hired_status = False
def __repr__(self):
return f'{self.first_name}, {self.last_name}, {self.phone_number}, {self.email_address}, {self.employee_job}, {self.hired_status}'
An updated load data function:
def load_employees(fn):
"""
Loads employees from text file fn.
- Retrieves comma-separated values from each line and assigns it to the corresponding arg in Employee()
- Adds the employee object to the employee_dict.
"""
employee_dict = dict()
with open(fn, 'r') as file:
for l in file.readlines():
itms = l.split(',')
emp = Employee(fname= itms[0].strip(),
lname = itms[1].strip(),
phone= itms[2].strip(),
email = itms[3].strip(),
job = itms[4].strip(),
interview_rating = itms[5].strip(),
hired_status = True if itms[6].strip().lower() == 'y' else False)
employee_dict[emp.full_name] = emp
return employee_dict
A couple of Enumerated Constant classes
class job_titles(Enum):
Cook = auto()
Dishwasher = auto()
Server = auto()
class food_handlers(Enum):
Cook = True
Dishwasher = False
Server = True
class cook_certs(Enum):
Basic = 1
Advanced = 2
A new class to manage the GUI interface
# Class to display the Employee Gui and Manage all related employee methods
class EmployeeForm():
def __init__(self, employee_list):
self.emp_list = employee_list
self.selected_employee = None
self.win = tk.Tk()
self.win.title("Employee Management Form")
self.win.config(bg='skyblue', pady=20, padx=50)
self.build_menuBar(self.win)
self.build_list_frame(self.win)
self.win.mainloop()
def do_nothing(self):
#Stub for menu items not yetbimplements
pass
def get_currewnt_employees(self):
pass
def build_menuBar(self, frm):
""" Format the Menu bar """
def add_command(mnu, itm):
mnu.add_command(label= itm[0], command= itm[1])
def add_sub_menu(mnu, cmd_dict):
for ky in cmd_dict.keys():
if len(cmd_dict[ky]) > 0:
mi = tk.Menu(mnu, tearoff= 0)
mnu.add_cascade(label=ky, menu=mi)
for itm in cmd_dict[ky]:
if type(itm) == tuple:
add_command(mi, itm)
else:
add_sub_menu(mi, itm)
menuoptions = {'File': [('Save Employee', self.do_nothing),
('Edit Employee', self.do_nothing),
('Delete Employee', self.do_nothing),
('Save All Changes', self.do_nothing)],
'View': [('Employee Management', self.do_nothing),
('Employee Rating', self.do_nothing)],
}
mbar = tk.Menu(frm)
add_sub_menu(mbar, menuoptions)
frm.config(menu=mbar)
return mbar
def select_employee(self, event):
selection = event.widget.curselection()
if self.selected_employee != self.cur_emps[selection[0]]:
self.selected_employee = self.cur_emps[selection[0]]
# if selection:
# index = selection[0]
# data = event.widget.get(index)
def build_list_frame(self, parent):
""" frame to display list of current employees. Always visible as per instructions"""
self.emp_list_frm = tk.Frame(parent, bg='skyblue', relief= tk.RAISED, borderwidth= 5)
self.emp_list_frm.grid(row= 0 , sticky= (tk.E, tk.W))
emp_list_lbl = tk.Label(self.emp_list_frm, text='Current Employees',
bg='systembuttonface', justify= tk.CENTER)
emp_list_lbl.grid(row=0, column=1, sticky= (tk.E, tk.W))
self.cur_emps = list(x for x in sorted(self.emp_list.keys()))
self.emp_list_dsply = tk.Listbox(self.emp_list_frm, width=75,
listvariable =tk.StringVar(value= self.cur_emps) )
self.emp_list_dsply.grid(row=1, columnspan=3)
self.emp_list_dsply.bind("<<ListboxSelect>>", self.select_employee)
To run the above:
emp_file = 'employees.txt'
emplist = load_employees(emp_file)
EmployeeForm(load_employees(emp_file))
Once you select an employee from the listbox selection options, the contents of self.selected_employee will reflect the employee object which then can be referenced by the delete method, and the edit method for further actions.
I've been experimenting with a sqlite3 for the first time and was developing a login system (with some help from articles and videos) and have noticed that all credentials inputted into the program are being accepted, I can't find a fault in the program so I could use some help.
Importing Important Libraries
import sqlite3
import bcrypt
class Database:
def __init__(self):
try:
self.conn = sqlite3.connect("usertable.db")
print("Successfully Opened Database")
self.curr = self.conn.cursor()
except:
print("Failed")
def createTable(self):
create_table = '''
CREATE TABLE IF NOT EXISTS cred(
id Integer PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL,
password TEXT NOT NULL
);
'''
self.curr.execute(create_table)
self.conn.commit()
def insertData(self, data):
insert_data = """
INSERT INTO cred(username, password)
VALUES(?, ?);
"""
self.curr.execute(insert_data, data)
self.conn.commit()
def searchData(self, data):
search_data = '''
SELECT * FROM cred WHERE username = (?);
'''
self.curr.execute(search_data, data)
rows = self.curr.fetchall()
if rows == []:
return 1
return 0
def validateData(self, data, inputData):
validate_data = """
SELECT * FROM cred WHERE username = (?);
"""
self.curr.execute(validate_data, data)
row = self.curr.fetchall()
if row[0][1] == inputData[0]:
return row[0][2] == bcrypt.hashpw(inputData[1].encode(), row[0][2])
(The login and register classes)
from tkinter import *
from tkinter import messagebox
import bcrypt
from database import Database
db = Database()
db.createTable()
class Login:
def __init__(self):
self.loginWindow = Tk()
self.loginWindow.title("Login")
self.loginWindow.geometry("300x250")
self.label = Label(self.loginWindow, text="Login")
self.label.place(x=95, y=40)
self.usernames = StringVar()
self.passwords = StringVar()
self.usernameE = Entry(self.loginWindow, relief=FLAT, textvariable=self.usernames)
self.usernameE.place(x=70, y=80)
self.passwordE = Entry(self.loginWindow, show="*", relief=FLAT, textvariable = self.passwords)
self.passwordE.place(x=70, y=120)
self.username = self.usernames.get()
self.password = self.passwords.get()
self.submit = Button(self.loginWindow, text = "Submit", pady = 5, padx = 20, command = self.validate)
self.submit.place(x=100, y=150)
def validate(self):
data = (self.username,)
inputData = (self.username, self.password,)
try:
if (db.validateData(data, inputData)):
messagebox.showinfo("Successful", "Login Was Successful")
else:
messagebox.showerror("Error", "Wrong Credentials")
except IndexError:
messagebox.showerror("Error", "Wrong Credentials")
def run(self):
self.loginWindow.mainloop()
class Register:
def __init__(self):
self.registerWindow = Tk()
self.registerWindow.title("Register")
self.registerWindow.geometry("300x250")
self.label = Label(self.registerWindow, text="Register")
self.usernameS = StringVar()
self.passwordS = StringVar()
self.usernameE = Entry(self.registerWindow, relief = FLAT, textvariable = self.usernameS)
self.usernameE.place(x=70, y=80)
self.passwordE = Entry(self.registerWindow, show="*", relief = FLAT, textvariable = self.passwordS)
self.passwordE.place(x=70, y=120)
self.submit = Button(self.registerWindow, text="Submit", pady = 5, padx = 20, command = self.add)
self.submit.place(x=100, y=150)
self.username = self.usernameS.get()
self.password = self.passwordS.get()
self.salt = bcrypt.gensalt()
self.hashed = bcrypt.hashpw(self.password.encode(), self.salt)
def run(self):
self.registerWindow.mainloop()
def add(self):
data = (self.username,)
result = db.searchData(data)
print(result, result, result)
if result != 0:
data = (self.username, self.hashed)
db.insertData(data)
messagebox.showinfo("Successful", "Username Was Added")
else:
messagebox.showwarning("Warning", "Username already Exists")
(The main window class)
from tkinter import *
from login import Login, Register
class Window(object):
def __init__(self):
self.window = Tk()
self.window.title("Login Screen")
self.window.geometry("300x250")
self.label = Label(self.window, text = "Welcome to Login")
self.label.place(x=95, y=40)
self.login = Button(self.window, text = "Login", pady = 5, padx = 30, command = login)
self.login.place(x=100, y=100)
self.register = Button(self.window, text = "Register", pady = 5, padx = 20, command = register)
self.register.place(x=100, y=150)
def run(self):
self.window.mainloop()
def login():
loginTk = Login()
loginTk.run()
def register():
registerTk = Register()
registerTk.run()
window = Window()
window.run()
The program is stored in 3 different files (the login and register classes are stored within the same file.)
I have a issue when I want to populate a entry box using tkinter. My current script are calling another script to get values. Then I want the data to be displayed in a Tkinter entry box.
This is my current code, I am have tried tbName.set("tbName", account.getName()) somethhing like that (with and without the tbName) I have also triws StringVar. I am not sure if I am using it wrong. I have looked at the following site : effbot. I am very new to Python so any help will b apritiated.
from Tkinter import *
from bank import Bank, SavingsAccount
class BankManager(object):
root = Tk()
lblName = Label(root, text="Name")
lblPin = Label(root, text="Pin")
lblBalance = Label(root, text="Balance R")
lblStatus = Label(root, text="Status")
tbName = Entry(root)
tbPin = Entry(root)
tbBalance = Entry(root)
tbStatus = Entry(root)
def __init__(self):
self.bank = None
self.app = None
self.current_index = 0
self.create_bank()
self.populate_gui(self.current_index)
def new_account(self, event):
name = self.app.getEntry('name')
pin = self.app.getEntry('pin')
balance = self.app.getEntry('balance')
account = self.bank.get(pin)
if account:
self.app.setEntry("status", "Account with pin exists")
else:
self.bank.add(SavingsAccount(name, pin, float(balance)))
self.app.setEntry("status", "New account created")
self.current_index = self.bank.getPins().index(pin)
btnNewAcc = Button(root,text="New Account")
btnNewAcc.bind("<Button>",new_account)
def update_account(self, event):
name = self.app.getEntry('name')
pin = self.app.getEntry('pin')
balance = self.app.getEntry('balance')
account = self.bank.get(pin)
if account:
account._name = name
account._balance = balance
self.app.setEntry("status", "Account updated")
else:
self.app.setEntry("status", "Account with pin doesn't exist")
btnUpdateAcc = Button(root, text="Update Account")
btnUpdateAcc.bind("<Button>",update_account)
def remove_account(self, event):
pin = self.app.getEntry('pin')
account = self.bank.get(pin)
if account:
self.bank.remove(pin)
self.app.setEntry("status", "Account removed")
self.current_index = 0
else:
self.app.setEntry("status", "Account with pin doesn't exist")
btnRemoveAcc = Button(root,text="Remove Account")
btnRemoveAcc.bind("<Button>",remove_account)
def compute_interest(self, event):
self.bank.computeInterest()
pin = self.app.getEntry('pin')
account = self.bank.get(pin)
if account:
self.app.setEntry("status", "Interest updated")
self.app.setEntry("balance", str(account.getBalance()))
else:
self.app.setEntry("status", "Account with pin doesn't exist")
btnConputeInterest = Button(root,text="Compute Interest")
btnConputeInterest.bind("<Button>",compute_interest)
def press_navigator(self, event):
if button == "Previous":
if self.current_index == 0:
self.current_index = len(self.bank.getPins()) - 1
else:
self.current_index -= 1
elif button == "Next":
if self.current_index == len(self.bank.getPins()) - 1:
self.current_index = 0
else:
self.current_index += 1
self.populate_gui(self.current_index)
btnPrevious = Button(root,text="Previous")
btnPrevious.bind("<Button>",press_navigator)
btnNext = Button(root,text="Next")
btnNext.bind("<Button>",press_navigator)
lblName.grid(row=0)
lblPin.grid(row=1)
lblBalance.grid(row=2)
lblStatus.grid(row=3)
tbName.grid(row=0, column=1)
tbPin.grid(row=1, column=1)
tbBalance.grid(row=2, column=1)
tbStatus.grid(row=3, column=1)
btnNewAcc.grid(row=0, column=2)
btnUpdateAcc.grid(row=1, column=2)
btnRemoveAcc.grid(row=2, column=2)
btnConputeInterest.grid(row=3, column=2)
btnPrevious.grid(row=4, column=0)
btnNext.grid(row=4, column=1)
root.mainloop()
def create_bank(self):
self.bank = Bank()
a1 = SavingsAccount('zzz', '111', 100)
a2 = SavingsAccount('yyy', '222', 200)
a3 = SavingsAccount('xxx', '333', 300)
self.bank.add(a1)
self.bank.add(a3)
self.bank.add(a2)
def populate_gui(self, index):
account = self.bank.get(self.bank.getPins()[index])
tbName.set("tbName", account.getName())
if __name__ == '__main__':
BankManager()
if you want to set text in the Entry widget, you need to use Entry.insert(0,'text') instead of v.set. The 0 in the insert method is the place you want to insert the text, in this case it is in the beginning of the Entry.
If you don't want the user to edit what is inside the Entry, you can use Entry.config(state='readonly'); if you want to edit the content later you need to call Entry.config(state=NORMAL) before you can use Entry.insert again. You don't need to set StringVar to the Entry, only using Entry.get() is sufficient.