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.
Related
As you can see, I can store passwords here.
I have to add a feature that I can register a new user. How do I do it so that I can create new instances when creating a new user?
import datetime
import getpass
class User:
def __init__(self, username, mail, date_of_birth, gender, password):
self.username = username
self.mail = mail
self.date_of_birth = datetime.datetime.strptime(date_of_birth, "%d.%m.%Y").date()
self.gender = gender
self.password = password
def get_username(self):
return self.username
def get_mail(self):
return self.mail
def get_date_of_birth(self):
return self.date_of_birth
def get_gender(self):
return self.gender
def get_password(self):
self.password
def get_date(self):
return self.date_of_birth
log = ""
def tries_left(self):
max_tries = 3
trie = 0
while trie <= max_tries:
print("wrong password!")
print("tries left " + str(max_tries - trie + 1))
trie +=1
pwrd = input("input password")
if pwrd != self.password:
pass
else:
self.login_or_register()
def login2(self):
global log
log = input("input your username: ")
if log == self.username:
pwrd = input("whats your password?")
if pwrd == self.password:
print("Logged in!")
self.add_password_orCheck_password()
else:
self.tries_left()
else:
print("wrong username!")
self.login2()
def login_or_register(self):
user_input = input("Login or Register: ")
if user_input == "login":
self.login2()
elif user_input == "register":
pass
else:
print("Try again!")
self.login_or_register()
def add_password(self):
global sitepassword
global Site
Site = input("Enter site name: ")
sitepassword = input("Enter password")
self.add_password_orCheck_password()
global passwords
passwords = {Site: sitepassword}
def check_passwords(self):
global passwords
global sitepassword
global Site
passwords = {Site: sitepassword}
which_password = input("Which sites password do you want to see?")
for Site in passwords:
if which_password in passwords:
print(sitepassword)
self.add_password_orCheck_password()
def add_password_orCheck_password(self):
add_new = input("Do you want to add a password or check passwords?")
if "add a password" in add_new:
self.add_password()
elif "check passwords" in add_new:
self.check_passwords()
Matt = User("Matterson", "matt#gmail.com", "21.12.1999" ,"male", "Password987")
session1 = Matt.login_or_register()
i wasnt thinking here is a better option:
users = {}
while True:
name = input('yourtexthere')
email = input('yourtexthere')
year = input('yourtexthere')
gender = input('yourtexthere')
password = input('yourtexthere') # here you will use getpass
users[f'{name}'] = User(name, email, year, gender, password)
however you can also store them in list but then you will have to access them by index and you may want to use the email as a key:
users[f'{email}'] = User(name, email, year, gender, password)
here is the code (refer to my comment) its not the cleanest one but it works, here you can try implementing your User class and making it as you need however you need experience in tkinter (this is just an example) hope it helps (it also creates the json file (if it is not already created) in this codes directory) (and I hope this aint against some guidlines):
from tkinter import *
from tkinter import messagebox
import json
all_user_pass = dict()
try:
with open('stored_data.json') as file:
data = json.load(file)
except:
with open('stored_data.json', 'w') as file:
json.dump(all_user_pass, file, indent=2)
with open('stored_data.json') as file:
data = json.load(file)
class MainWindow(Toplevel):
def __init__(self, parent):
self.parent = parent
Toplevel.__init__(self, parent)
self.x_tk = 310
self.y_tk = 100
self.win_h = int(self.winfo_screenheight()/2 - self.y_tk/2)
self.win_w = int(self.winfo_screenwidth()/2 - self.x_tk/2)
self.geometry(f"{str(self.x_tk)}x{str(self.y_tk)}+{str(self.win_w)}+{str(self.win_h)}")
self.title('Login')
self.protocol('WM_DELETE_WINDOW', self.quit)
self.username = Entry(self, bg="grey", bd=5, font="none 12 normal")
word_username = Label(self, text='Username:')
word_username.grid(row=0, column=0, sticky='w')
self.username.grid(row=0, column=1)
self.password = Entry(self, bg="grey", bd=5, font="none 12 normal")
word_password = Label(self, text='Password:')
word_password.grid(row=1, column=0, sticky='w')
self.password.grid(row=1, column=1)
login_button = Button(self, text='Login', command=self.login)
login_button.grid(row=2, column=0)
self.bind('<Return>', self.login)
signup_button = Button(self, text='Sign Up', command=self.open_signup)
signup_button.grid(row=2, column=2)
self.incorrect_user_or_pass = Label(self, text='Incorrect username or password!')
self.empty_user_or_pass = Label(self, text='Cannot be blank!')
def open_signup(self):
signupwindow = SignUpWindow(self)
signupwindow.focus_force()
signupwindow.withdraw
def login(self, event=None):
global data
existing_user = self.username.get()
user_pass = self.password.get()
self.incorrect_user_or_pass.place_forget()
if existing_user != '' and user_pass != '':
if existing_user in data and data[existing_user] == user_pass:
messagebox.showinfo('Successful Login', 'You have logged in successfully!', parent=self)
self.username.delete(0, 'end')
self.password.delete(0, 'end')
self.empty_user_or_pass.place_forget()
self.incorrect_user_or_pass.place_forget()
else:
self.username.delete(0, 'end')
self.password.delete(0, 'end')
self.empty_user_or_pass.place_forget()
self.incorrect_user_or_pass.place(x=60, y=65)
else:
self.empty_user_or_pass.place(x=90, y=65)
class SignUpWindow(Toplevel):
def __init__(self, parent):
self.parent = parent
Toplevel.__init__(self, parent)
self.x_tk = 310
self.y_tk = 100
self.win_h = int(self.parent.winfo_rooty() - 31)
self.win_w = int(self.parent.winfo_rootx() - 8)
self.geometry(f"{str(self.x_tk + 16)}x{str(self.y_tk + 39)}+{str(self.win_w)}+{str(self.win_h)}")
self.title('Signup')
self.bind('<FocusOut>', self.f_out_main)
self.bind('<Escape>', self.close)
self.update_idletasks()
self.overrideredirect(True)
self.config(bg='green')
Label(self, text='Signup', font='none 20 normal', bg='green', bd=5) .grid(row=0, column=0, columnspan=4)
self.username = Entry(self, bg="grey", bd=5, font="none 12 normal")
word_username = Label(self, text='Username:', bg='green')
word_username.grid(row=1, column=0, sticky='w')
self.username.grid(row=1, column=1)
self.username.bind('<FocusOut>', self.f_out)
self.password = Entry(self, bg="grey", bd=5, font="none 12 normal")
word_password = Label(self, text='Password:', bg='green')
word_password.grid(row=2, column=0, sticky='w')
self.password.grid(row=2, column=1)
self.password.bind('<FocusOut>', self.f_out)
cancel_button = Button(self, text='Cancel', command=self.cancel)
cancel_button.grid(row=3, column=0)
cancel_button.bind('<FocusOut>', self.f_out)
cancel_button.bind('<Return>', self.cancel)
signup_button = Button(self, text='Sign Up', command=self.signup)
signup_button.grid(row=3, column=2)
signup_button.bind('<FocusOut>', self.f_out)
self.bind('<Return>', self.signup)
self.user_taken = Label(self, text='Username already taken!', bg='green')
self.empty_user_or_pass = Label(self, text='Cannot be blank!', bg='green')
self.focus_list = []
def f_out(self, event=None):
self.focus_list.append('focus_out_of_widget')
def f_out_main(self, event=None):
self.focus_list.append('focus_out_of_window')
if len(self.focus_list) >= 2:
if self.focus_list[-2] == 'focus_out_of_window' and self.focus_list[-1] == 'focus_out_of_window':
self.close()
elif self.focus_list[0] == 'focus_out_of_window':
self.close()
def cancel(self, event=None):
self.destroy()
def signup(self, event=None):
global all_user_pass
global data
new_username = self.username.get()
new_password = self.password.get()
if new_username != '' and new_password != '':
if new_username not in data:
if new_username not in all_user_pass:
all_user_pass[new_username] = new_password
data.update(all_user_pass)
with open('stored_data.json', 'w') as f:
json.dump(data, f, indent=2)
self.username.delete(0, 'end')
self.password.delete(0, 'end')
self.user_taken.place_forget()
self.empty_user_or_pass.place_forget()
self.destroy()
else:
self.username.delete(0, 'end')
self.password.delete(0, 'end')
self.empty_user_or_pass.place_forget()
self.user_taken.place(x=90, y=110)
else:
self.username.delete(0, 'end')
self.password.delete(0, 'end')
self.empty_user_or_pass.place_forget()
self.user_taken.place(x=90, y=110)
else:
self.empty_user_or_pass.place(x=90, y=110)
def close(self, event=None):
self.parent.focus_set()
self.destroy()
root = Tk()
root.withdraw()
app = MainWindow(root)
app.mainloop()
So I am creating a small data handler program that essentially allows the user to turn in a form that takes in values such as your address, city, name, email, etc. Pressing "View Personnel Data" opens up another Tkinter window which displays all the data that users have previously entered in (data which is stored in a text file and then read from to display the data). I have organized the data in columns in a secondary Tkinter window based on what the data is (e.g. address, city, etc). Of course, eventually, there won't be enough room in the windows to display all entries, and as such the user would want to be able to scroll through them. As a newbie to Tkinter and python in general, I am not sure as to how I would go about doing this. Below I have attached pictures of the windows that are displayed in my program and my code.
My code:
import tkinter as t
root = t.Tk()
root.title("Data Handler")
root.geometry('250x250')
#class viewPersons():
#def open(self):
def addPerson():
data = open('data.txt', 'a')
name = name_var.get()
email = email_var.get()
age = age_var.get()
state = state_var.get()
city = city_var.get()
address = address_var.get()
print(name+','+email+','+age+','+state+','+city+','+address)
data.write(name+','+email+','+age+','+state+','+city+','+address+'\n')
data.close()
viewopen=False
def viewWindow():
global viewopen
def on_close():
global viewopen
viewopen = False
view.destroy()
def onFrameConfigure(primarycanvas):
primarycanvas.configure(scrollregion=primarycanvas.bbox("all"))
if viewopen is False:
viewopen=True
view = t.Tk()
view.geometry('800x300')
primarycanvas = t.Canvas(view, borderwidth=0, background='#ffffff')
frame = t.Frame(primarycanvas, background='#ffffff')
vsb = t.Scrollbar(view, orient='vertical', command=primarycanvas.yview)
primarycanvas.configure(yscrollcommand=vsb.set)
vsb.pack(side="right", fill="y")
primarycanvas.pack(side="left", fill="both", expand=True)
primarycanvas.create_window((4, 4), window=frame, anchor="nw")
frame.bind("<Configure>", lambda event, primarycanvas=primarycanvas: onFrameConfigure(primarycanvas))
t.Label(frame,text='N͟a͟m͟e͟',borderwidth=2,relief='groove',font=(20)).grid(row=0,column=0)
t.Label(frame, text='E͟m͟a͟i͟l͟',borderwidth=2,relief='groove',font=(20)).grid(row=0, column=1)
t.Label(frame, text='A͟g͟e͟',borderwidth=2,relief='groove',font=(20)).grid(row=0, column=2)
t.Label(frame, text='S͟t͟a͟t͟e͟',borderwidth=2,relief='groove',font=(20)).grid(row=0, column=3)
t.Label(frame, text='C͟i͟t͟y͟',borderwidth=2,relief='groove',font=(20)).grid(row=0, column=4)
t.Label(frame, text='A͟d͟d͟r͟e͟s͟s͟',borderwidth=2,relief='groove',font=(20)).grid(row=0, column=5)
class Person():
def __init__(self, name, email, age, state, city, address, rowcounter):
self.name = name
self.email = email
self.age = age
self.state = state
self.city = city
self.address = address
self.rowcounter = rowcounter
def display(self):
t.Label(frame, text=self.name,font=(20)).grid(row=self.rowcounter,column=0)
t.Label(frame,text=self.email,font=(20)).grid(row=self.rowcounter,column=1)
t.Label(frame, text=self.age,font=(20)).grid(row=self.rowcounter, column=2)
t.Label(frame, text=self.state,font=(20)).grid(row=self.rowcounter, column=3)
t.Label(frame, text=self.city,font=(20)).grid(row=self.rowcounter, column=4)
t.Label(frame, text=self.address,font=(20)).grid(row=self.rowcounter, column=5)
data = open('data.txt', 'r+')
rowcounter=1
info = data.readlines()
persons = {}
person_id = 0
for x in info:
split = x.strip().split(',')
print(split)
person_id += 1
persons[person_id] = Person(split[0],split[1],split[2],split[3],split[4],split[5], rowcounter)
persons[person_id].display()
rowcounter += 1
print(persons)
data.close()
view.protocol('WM_DELETE_WINDOW', on_close)
view.mainloop()
name_var = t.StringVar()
email_var = t.StringVar()
age_var = t.StringVar()
state_var = t.StringVar()
city_var = t.StringVar()
address_var = t.StringVar()
t.Label(root, text='Name:').grid(row=0,padx=4)
name_ent = t.Entry(root, textvariable=name_var).grid(row=0,column=1,pady=4)
t.Label(root, text='Email:').grid(row=1,padx=4)
email_ent = t.Entry(root, textvariable=email_var).grid(row=1,column=1,pady=4)
t.Label(root, text='Age:').grid(row=2, padx=4)
age_ent = t.Entry(root, textvariable=age_var).grid(row=2,column=1,pady=4)
t.Label(root, text='State:').grid(row=3, padx=4)
state_ent = t.Entry(root, textvariable=state_var).grid(row=3,column=1,pady=4)
t.Label(root, text='City:').grid(row=4,padx=4)
city_ent = t.Entry(root, textvariable=city_var).grid(row=4,column=1,pady=4)
t.Label(root, text='Address:').grid(row=5,padx=4)
address_ent = t.Entry(root, textvariable=address_var).grid(row=5,column=1,pady=4)
t.Button(root, text='Submit',width=15,command=addPerson).grid(row=6,columnspan=2,ipadx=10)
t.Button(root,text='View Personnel Data',width=15,command=viewWindow).grid(row=7,columnspan=2,ipadx=10)
root.mainloop()
I created a class in order to create a batch of checkbuttons as follows.
I'm trying to get the chekbutton's number to indicate which one was pressed( with no success ).
stat functio, when called, sends status of all checkbuttons.
any ideas ?
class dev_buttons2(object):
def __init__(self,master,buts_list):
self.status=[]
for i in range(len(buts_list)):
self.var = IntVar()
self.name=buts_list[i]
self.c = Checkbutton(master,text=buts_list[i], variable=self.var,
indicatoron=0,command=self.cb,width=10,height=2)
self.c.grid(column=i, padx=5,row = 10)
self.status.append(self.var)
def cb(self):
print(self.name)
def stat():
return self.status
Using Lambda function - I passed as much values as I want to arg ( see comment at code ).
class SwitchButtons:
def __init__(self, master, frame, num_of_buttons):
self.master = master
self.status = []
self.buts = []
self.leds = []
bg_window = "DeepSkyBlue4"
self.framein = Frame(frame)
self.framein.grid(padx=5, pady=5)
#Create Widgets of buttons
for i in range(num_of_buttons):
button_var = StringVar()
entry_var = IntVar()
led_var = StringVar()
t = 35
ent = Entry(self.framein, textvariable=entry_var, width=4, justify="center")
ent.grid(column=i, row=2, sticky=W, padx=t)
led = Label(self.framein, textvariable=led_var, width=4, bg="red", fg="white", relief="ridge")
led_var.set("off")
led.grid(row=0, column=i, pady=0)
c = Checkbutton(self.framein, text="Switch " + str(i), variable=button_var, indicatoron=0,
width=10, height=2, onvalue="on", offvalue="off",
command=lambda arg=[i, button_var, entry_var]: #### Use Lambda to pass several arguments to "arg"
self.cb(arg))
c.grid(column=i, padx=30, pady=5, row=1)
button_var.set("off")
mins = Label(self.framein, text="min.", width=4, justify="center", fg="black")
mins.grid(column=i, row=2, sticky=E, padx=t)
self.status.append([button_var, led_var, entry_var])
self.buts.append(c)
self.leds.append(led)
###
def cb(self, but, state='', a=''):
# but = [ switch#, switch state, delay] ## explanatory
##In use only in CB_DELAYED
if state != '':
but[1].set(state)
def switch_onoff():
if but[1].get() == "on":
self.leds[but[0]].config(bg="green")
self.status[but[0]][1].set("on")
elif but[1].get() == "off":
self.leds[but[0]].config(bg="red")
self.status[but[0]][1].set("off")
if but[2].get() > 0 and but[1].get() == "on":
a = ", Auto shutdown in %s minutes." % (but[2].get())
switch_onoff()
print("Delayed", but[1].get())
self.cb_delayed(but)
else:
switch_onoff()
self.master.loop.device_chage_state(but[0], but[1].get(), text=a)
def cb_delayed(self, but):
self.framein.after(but[2].get() * 1000, self.cb, but, "off")
For my coursework i am doing a booking system which uses some tree views. The problem is that if ran from cmd when i double click on a row in the tree view it does not populate the boxes below it, however if i run it from the idle it does. Below is my where i have made my class and two defs which are create_GUI(for first part of gui before double click) and double click(makes second part of GUI)
from tkinter import *
import os
import datetime
import sqlite3
from tkinter.ttk import Combobox,Treeview,Scrollbar
import tkinter as tk
import Utilities
class Application(Frame):
""" Binary to Decimal """
def __init__(self, master):
""" Initialize the frame. """
super(Application, self).__init__(master)
self.grid()
self.create_GUI()
def Quit(self):
self.master.destroy()
def create_GUI(self):
frame1 = tk.LabelFrame(root, text="frame1", width=300, height=130, bd=5)
frame2 = tk.LabelFrame(root, text="frame2", width=300, height=130, bd=5)
frame1.grid(row=0, column=0, columnspan=3, padx=8)
frame2.grid(row=1, column=0, columnspan=3, padx=8)
self.title_lbl = Label(frame1, text = "Students")
self.title_lbl.grid(row = 0, column = 2)
self.fn_lbl = Label(frame1, text = "First Name:")
self.fn_lbl.grid(row = 1 , column = 1)
self.fn_txt = Entry(frame1)
self.fn_txt.grid(row = 1, column = 2)
self.ln_lbl =Label(frame1, text = "Last Name:")
self.ln_lbl.grid(row = 2, column = 1)
self.ln_txt = Entry(frame1)
self.ln_txt.grid(row = 2, column = 2)
self.q_btn = Button(frame1, text = "Back",padx=80,pady=10, command = lambda: self.Quit())
self.q_btn.grid(row = 3, column = 0)
self.s_btn = Button(frame1, text = "search",padx=80,pady=10, command = lambda: self.search())
self.s_btn.grid(row = 3,column = 3)
self.tree = Treeview(frame2,height = 6)
self.tree["columns"] = ("StudentID","First Name","Last Name")#,"House Number", "Street Name", "Town Or City Name","PostCode","MobilePhoneNumber")
self.tree.column("StudentID",width = 100)
self.tree.column("First Name",width = 100)
self.tree.column("Last Name", width = 100)
## self.tree.column("House Number", width = 60)
## self.tree.column("Street Name", width = 60)
## self.tree.column("Town Or City Name", width = 60)
## self.tree.column("PostCode", width = 60)
## self.tree.column("MobilePhoneNumber", width = 60)
self.tree.heading("StudentID",text="StudentID")
self.tree.heading("First Name",text="First Name")
self.tree.heading("Last Name",text="Last Name")
## self.tree.heading("House Number",text="House Number")
## self.tree.heading("Street Name",text="Street Name")
## self.tree.heading("Town Or City Name",text="Town Or City Name")
## self.tree.heading("PostCode",text="PostCode")
## self.tree.heading("MobilePhoneNumber",text="MobilePhoneNumber")
self.tree["show"] = "headings"
yscrollbar = Scrollbar(frame2, orient='vertical', command=self.tree.yview)
xscrollbar = Scrollbar(frame2, orient='horizontal', command=self.tree.xview)
self.tree.configure(yscroll=yscrollbar.set, xscroll=xscrollbar.set)
yscrollbar.grid(row=1, column=5, padx=2, pady=2, sticky=NS)
self.tree.grid(row=1,column=0,columnspan =5, padx=2,pady=2,sticky =NSEW)
self.tree.bind("<Double-1>",lambda event :self.OnDoubleClick(event))
def OnDoubleClick(self, event):
frame3 = tk.LabelFrame(root, text="frame1", width=300, height=130, bd=5)
frame3.grid(row=2, column=0, columnspan=3, padx=8)
self.message=StringVar()
self.message.set("")
self.lblupdate = Label(frame3, textvariable = self.message).grid(row=0,column=0,sticky=W)
curItem = self.tree.focus()
contents =(self.tree.item(curItem))
StudentDetails = contents['values']
print(StudentDetails)
self.tStudentID=StringVar()
self.tFirstName = StringVar()
self.tLastName = StringVar()
self.tHouseNumber = StringVar()
self.tStreetName = StringVar()
self.tTownOrCityName = StringVar()
self.tPostCode = StringVar()
self.tEmail = StringVar()
self.tMobilePhoneNumber = StringVar()
self.tStudentID.set(StudentDetails[0])
self.tFirstName.set(StudentDetails[1])
self.tLastName.set(StudentDetails[2])
self.tHouseNumber.set(StudentDetails[3])
self.tStreetName.set(StudentDetails[4])
self.tTownOrCityName.set(StudentDetails[5])
self.tPostCode.set(StudentDetails[6])
self.tEmail.set(StudentDetails[7])
self.tMobilePhoneNumber.set(StudentDetails[8])
self.inst_lbl0 = Label(frame3, text = "Student ID").grid(row=5,column=0,sticky=W)
self.StudentID = Label(frame3, textvariable=self.tStudentID).grid(row =5,column=1,stick=W)
self.inst_lbl1 = Label(frame3, text = "First Name").grid(row=6,column=0,sticky=W)
self.NFirstName = Entry(frame3, textvariable=self.tFirstName).grid(row =6,column=1,stick=W)
self.inst_lbl2 = Label(frame3, text = "Last Name").grid(row=7,column=0,sticky=W)
self.NLastName = Entry(frame3, textvariable=self.tLastName).grid(row =7,column=1,stick=W)
self.inst_lbl3 = Label(frame3, text = "House Number").grid(row=8,column=0,sticky=W)
self.HouseNumber = Entry(frame3,textvariable=self.tHouseNumber).grid(row=8,column=1,sticky=W)
self.inst_lbl4 = Label(frame3, text = "Street Name").grid(row=9,column=0,sticky=W)
self.StreetName =Entry(frame3,textvariable=self.tStreetName).grid(row=9,column=1,sticky=W)
self.inst_lbl5 = Label(frame3, text = "Town or City Name").grid(row=10,column=0,sticky=W)
self.TownOrCityName =Entry(frame3,textvariable=self.tTownOrCityName).grid(row=10,column=1,sticky=W)
self.inst_lbl6 = Label(frame3, text = "Postcode").grid(row=11,column=0,sticky=W)
self.PostCode = Entry(frame3,textvariable=self.tPostCode).grid(row=11,column=1,sticky=W)
self.inst_lbl7 = Label(frame3, text = "Email").grid(row=12,column=0,sticky=W)
self.Email =Entry(frame3,textvariable=self.tEmail).grid(row=12,column=1,sticky=W)
self.inst_lbl8 = Label(frame3, text = "Mobile phonenumber").grid(row=13,column=0,sticky=W)
self.MobilePhoneNumber =Entry(frame3,textvariable=self.tMobilePhoneNumber).grid(row=13,column=1,sticky=W)
self.btnSaveChanges = Button(frame3, text = "save changes",padx=80,pady=10,command = lambda:self.SaveChanges()).grid(row=14,column=0,sticky=W)
self.btnSaveChanges = Button(frame3, text = "delete record",padx=80,pady=10,command = lambda:self.DeleteRecord()).grid(row=14,column=1,sticky=W)
def search(self):
FirstName = self.fn_txt.get()
LastName = self.ln_txt.get()
with sqlite3.connect("GuitarLessons.db") as db:
cursor = db.cursor()
cursor.row_factory = sqlite3.Row
sql = "select StudentID,FirstName,LastName,HouseNumber,StreetName,TownOrCityName,PostCode,Email,MobilePhoneNumber"\
" from tblStudents"\
" where FirstName like ?"\
" and LastName like ?"
cursor.execute(sql,("%"+FirstName+"%","%"+LastName+"%",))
StudentList = cursor.fetchall()
print(StudentList)
self.loadStudents(StudentList)
def loadStudents(self,StudentList):
for i in self.tree.get_children():
self.tree.delete(i)
for student in StudentList:
self.tree.insert("" , 0,values=(student[0],student[1],student[2],student[3],student[4],student[5],student[6],student[7],student[8]))
def SaveChanges(self):
valid = True
self.message.set("")
NFirstName = self.tFirstName.get()
NLastName = self.tLastName.get()
NHouseNumber = self.tHouseNumber.get()
NStreetName = self.tStreetName.get()
NTownOrCityName = self.tTownOrCityName.get()
NPostCode = self.tPostCode.get()
NEmail = self.tEmail.get()
NMobilePhoneNumber = self.tMobilePhoneNumber.get()
StudentID = self.tStudentID.get()
if NFirstName == "" or NLastName == "" or NEmail == "" or NMobilePhoneNumber == "":
valid = False
self.message.set('missing details,first name,last name,phone number, email are all needed')
if not Utilities.is_phone_number(NMobilePhoneNumber ):
valid = False
self.message.set('invalid mobile phone number')
if not Utilities.is_postcode(NPostCode):
valid = False
self.message.set('invalid postcode')
if not Utilities.is_email(NEmail):
valid = False
self.message.set('invalid email')
if NHouseNumber != "":
if int(NHouseNumber) < 0:
self.message.set('invalid house number')
if valid == True:
with sqlite3.connect("GuitarLessons.db") as db:
cursor = db.cursor()
sql = "update tblStudents set FirstName =?,LastName=?,HouseNumber=?,StreetName=?,TownOrCityName=?,PostCode=?,Email=?,MobilePhoneNumber=? where StudentID=?"
cursor.execute(sql,(NFirstName,NLastName,NHouseNumber,NStreetName,NTownOrCityName,NPostCode,NEmail,NMobilePhoneNumber,StudentID))
db.commit()
self.message.set("student details updated")
def DeleteRecord(self):
StudentID = self.tStudentID.get()
#StudentID = int(StudentID)
with sqlite3.connect("GuitarLessons.db") as db:
cursor = db.cursor()
sql = "delete from tblStudents where StudentID = ?"
cursor.execute(sql,(StudentID))
db.commit()
self.tlabeupdate.set("student details deleted")
root = Tk()
root.title("booking system")
root.geometry("800x800")
root.configure(bg="white")
app = Application(root)
root.mainloop()
EDIT
when i was copyign and pasting the rest of my code that i forgot to put in the original post i found that it only stops working if i open it through the student menu(separate peice of code) but it works if i dont go through the menu
You must call mainloop() on the root window so that your program can process events.
You create LabelFrames in the parent called root, but root does not exist. To correct it pass master to the function, which receives it as root
class Application():
""" Binary to Decimal """
def __init__(self, master):
""" Initialize the frame. """
self.create_GUI(master)
def create_GUI(self, root):
frame1 = tk.LabelFrame(root, text="frame1", width=300, height=130, bd=5)
Im trying to create a Python tkinter login registeration but running into a small issue.
The error message is:
self.Label_Name = Label(top, text="What is your username: ")
AttributeError: Label instance has no __call__ method
Please can you proof read my code:
from Tkinter import *
class Register:
def __init__(self, parent):
top = self.top = Toplevel(parent)
# Variables to store the entries
self.VarEntUser = StringVar()
self.VarEntPass = StringVar()
self.VarEntRetype = StringVar()
self.Label_Name = Label(top, text="What is your username: ")
self.Label_Password = Label(top, text="Enter a password: ")
self.Label_Retype = Label(top, text="Retype Password: ")
# Entry fields for the user to enter there details
self.Ent_Name = Entry(top, textvariable=self.VarEntUser)
self.Ent_Password = Entry(top, textvariable=self.VarEntPass)
self.Ent_Retype = Entry(top, textvariable=self.VarEntRetype)
# Puts all the fields ^, into the window
self.Label_Name.grid(row=0, sticky=W)
self.Label_Password.grid(row=1, sticky=W)
self.Label_Retype.grid(row=2, sticky=W)
self.Ent_Password.grid(row=1, column=1)
self.Ent_Retype.grid(row=2, column=1)
self.Ent_Name.grid(row=0, column=2)
# Run the RegisterCheck function
# submit button which Checks the Entered details then writes the user and pass to a .txt file
self.MySubmitButton = Button(top, text='Submit', command=RegisterCheck)
self.MySubmitButton.pack()
self.U = raw_input(self.VarEntUser.get())
self.P = raw_input(self.VarEntPass.get())
self.R = raw_input(self.VarEntRetype.get())
class LogIn:
def __init__(self, parent):
top = self.top = Toplevel(parent)
self.a = StringVar()
self.b = StringVar()
self.Label_Log_User1 = Label(top, text='Username:')
self.Label_Log_Pass = Label(top, text='Password: ')
self.Ent_User_Log = Entry(top, textvariable=self.a)
self.Ent_Pass_Log = Entry(top, textvariable=self.b)
self.Label_Log_User1.grid(row=1)
self.Pass_Log.grid(row=2)
self.EntUserLog.grid(row=1, column=1)
self.EntPassLog.grid(row=2, column=1)
self.User = raw_input(self.EntUserLog.get())
self.Pass = raw_input(self.EntUserLog.get())
# runs the 'LoginCheck' function
self.LogInButton = Button(top, text="Log In", command=LogInCheck)
self.LogInButton.pack()
def LogInCheck(self):
# Checks if the fields are blanking displaying an error
if len(self.User) <= 0 and len(self.Pass) <= 0:
print "Please fill in all fields."
else:
pass
# Checks to see if the user and pass have been created
if self.User in 'username.txt' and self.Pass in 'password':
print 'You are now logged in!'
else:
print "Log in Failed"
def RegisterCheck(self):
# Checks if the fields are blank
if len(self.P) <= 0 and len(self.U) <= 0:
print "Please fill out all fields."
else:
pass
# Check is the password and the retype match
if self.P == self.R:
pass
else:
print "Passwords do not match"
# After registering write the user and pass to a .txt file
with open('username.txt', 'a') as fout:
fout.write(self.U + '\n')
with open('password.txt', 'a') as fout:
fout.write(self.P + '\n')
# Depending on what the user chooses, either log in or register than opens the specific window
def launch_Register():
inputDialog = Register(root)
root.wait_window(inputDialog.top)
def launch_LogIn():
inputdialog2 = LogIn(root)
root.wait_window(inputdialog2.top)
root = Tk()
label = Label(root, text='Choose an option')
label.pack()
loginB = Button(root, text='Log In', command=launch_LogIn)
loginB.pack()
registerB = Button(root, text='Register', command=launch_Register)
registerB.pack()
root.mainloop()
The problem is that in this line
Label = Label(root, text='Choose an option')
you define a Label called Label, thus shadowing the Label constructor. Then, then you create the several labels in your Register and Login classes (triggered by those two buttons), the name Label is no longer bound to the constructor, but to that specific label.
Change the name of the label, then it should work. Also, I would advise you to use lower-case names for variables and methods. This alone might help prevent many such errors.
root = Tk()
label = Label(root, text='Choose an option')
label.pack()
loginB = Button(root, text='Log In', command=launch_LogIn)
loginB.pack()
registerB = Button(root, text='Register', command=launch_Register)
registerB.pack()
root.mainloop()
Note that there are a few many more problems with your code:
StringVar a and b should probably be self.a and self.b
You are trying to use raw_input to get the user input in the Entry widgets; this is wrong! Instead, just read the value of the variables to get the values, e.g. instead of self.User, use self.a.get()
do not mix grid and pack layout
if self.User in 'username.txt' will not check whether that name is in that file
loginCheck and registerCheck should be methods of the respective class
Once I'm at it, here's (part of) my version of your code, to help you getting started:
class Register:
def __init__(self, parent):
top = self.top = Toplevel(parent)
self.var_user = StringVar()
self.var_pass = StringVar()
self.var_retype = StringVar()
Label(top, text="What is your username: ").grid(row=0, sticky=W)
Label(top, text="Enter a password: ").grid(row=1, sticky=W)
Label(top, text="Retype Password: ").grid(row=2, sticky=W)
Entry(top, textvariable=self.var_user).grid(row=0, column=1)
Entry(top, textvariable=self.var_pass).grid(row=1, column=1)
Entry(top, textvariable=self.var_retype).grid(row=2, column=1)
Button(top, text='Submit', command=self.registerCheck).grid(row=3)
def registerCheck(self):
u, p, r = self.var_user.get(), self.var_pass.get(), self.var_retype.get()
if p and u:
if p == r:
logins[u] = p
else:
print "Passwords do not match"
else:
print "Please fill out all fields."
class LogIn:
# analogeous to Register; try to figure this out xourself
def launch_Register():
inputDialog = Register(root)
root.wait_window(inputDialog.top)
def launch_LogIn():
inputDialog = LogIn(root)
root.wait_window(inputDialog.top)
logins = {}
root = Tk()
Label(root, text='Choose an option').pack()
Button(root, text='Log In', command=launch_LogIn).pack()
Button(root, text='Register', command=launch_Register).pack()
root.mainloop()
Note that I changed the login "database" from files to a dictionary to keep things simple and to focus on the Tkinter problems. Of course, neither a simple dictionary nor a plain-text file is an appropriate way to store login information.
Also, I put the creation and the layout of the GUI widgets on one line. In this case this is possible since we do not need a reference to those widgets, but beware never to do e.g. self.label = Label(...).grid(...), as this will bind self.label to the result of grid, and not to the actual Label.
Finally, this will still print all the messages to the standard output. Instead, you should add another Label for that, or open a message dialogue, but this is left as an excercise to the reader...