Demo entry 6783281

matt

   

Submitted by Shannon on Feb 06, 2019 at 15:55
Language: Python 3. Code size: 55.7 kB.

import tkinter as tk
from tkinter import ttk
import sqlite3
import datetime
import re

#this class is used to create the different frames/windows of the program
class Start(tk.Tk): 
    #the initalisation creates the dictionary that will store the different frames/windows of the system
    def __init__(self, *args, **kwargs): 
        
        tk.Tk.__init__(self, *args, **kwargs)

        self.resizable(False, False) #can't change size of window
        
        container = tk.Frame(self)  

        container.grid()
        
        self.frames = {}

        #adds the different frames in the program to the dictionary and formats them
        for F in (Login, Menu, FixRes, Manage, Players): 
            
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew") 

        self.showFrame(Login) 

    #when called with display the window passed, each the windows are formated here
    def showFrame(self, cont): 
            
        for frame in self.frames.values():
            frame.grid_remove()
        frame = self.frames[cont]
        frame.grid()

        if cont==Login: 
            frame.winfo_toplevel().geometry("205x95")
            self.title("Log-in")
        elif cont==Menu:
            frame.winfo_toplevel().geometry("240x130")
            self.title("Main menu")
        elif cont==FixRes:
            frame.winfo_toplevel().geometry("960x230")
            self.title("Fixtures and results")
        elif cont==Manage:
            frame.winfo_toplevel().geometry("470x180")
            self.title("Manage users")
        elif cont==Players:
            frame.winfo_toplevel().geometry("440x270")
            self.title("Player information")
            page = self.getPage(Players) #instantiation
            page.mainSelect()

    #this method returns the frame page, used for instantiation
    def getPage(self, page_class): 
        
        return self.frames[page_class]

#the login window, first window displayed when program run
class Login(tk.Frame): 
    
    CheckAdmin = 0 #this value is to see whether the admin is logged in or not

    #the initialisation creates all the widgets for the window and creates the login database
    def __init__(self, parent, controller): 
        tk.Frame.__init__(self,parent)

        self.controller = controller

        label1 = tk.Label(self,text="Username:") 
        label1.grid(row=1,column=0, sticky="w") 
        
        label2 = tk.Label(self,text="Password:") 
        label2.grid(row=2,column=0, sticky="w")

        self.entry1 = tk.Entry(self) 
        self.entry1.grid(row=1, column=1)
        
        self.entry2 = tk.Entry(self)
        self.entry2.grid(row=2, column=1)

        self.tick = tk.IntVar()
        
        check = tk.Checkbutton(self, command=self.changePass, text= "Hide password", variable=self.tick) 
        check.grid(row=3,columnspan=3)

        button = tk.Button(self, text="Login", command=self.logIn)
        button.grid(row=4,columnspan=3)

        conn = sqlite3.connect("football.db") 
        c = conn.cursor()

        #c.execute("""CREATE TABLE login (
        #          userID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
        #          forename TEXT,
        #          surname TEXT,
        #          username TEXT,
        #          password TEXT
        #           )""")

        #c.execute("INSERT INTO login VALUES ('1','admin','admin','admin', 'password')")

        conn.commit()
        conn.close()

    #when the checkbutton is clicked, the password is hidden
    def changePass(self):
        
        if self.tick.get()==1:
            self.entry2.config(show='*') 
        else:
            self.entry2.config(show='') 

    #returns the CheckAdmin value, this is value checks whether the admin is logged in or not
    def getCheckAdmin(self): 
        
        return self.CheckAdmin

    #this is called to change the value of the object
    def setCheckAdmin(self, CheckAdmin):
        
        self.CheckAdmin = CheckAdmin 

    #when the login button is pressed this method is run to see whether the details are correct
    def logIn(self): 
        
        conn = sqlite3.connect("football.db") 
        c = conn.cursor()
    
        c.execute("SELECT username, password FROM login") 
        
        self.usr = [] 
        self.psswrd = []
        #appends username and password values from the database into lists
        for column in c.fetchall():
            self.usr.append(column[0])
            self.psswrd.append(column[1])

        #checks the if the details entered are correct, if thet are the menu window is loaded
        #otherwise error message displayed
        if ((self.entry1.get() in self.usr) and (self.entry2.get() in self.psswrd)
            and self.usr.index(self.entry1.get())==self.psswrd.index(self.entry2.get())):

            #if the admin is logged in the value is set to 1 
            if self.entry1.get()=="admin": 
               self.setCheckAdmin(1)
            else:
                ()

            self.entry1.delete(0, 'end') 
            self.entry2.delete(0, 'end')
            
            self.controller.showFrame(Menu)          
        else:
            self.error() 
             
            self.entry1.delete(0, 'end') 
            self.entry2.delete(0, 'end')

        conn.commit()
        conn.close()

    #if the user enters incorrect details, then a error window is displayed
    def error(self): 
        
        self.top = tk.Toplevel() 

        label3 = tk.Label(self.top, text="The user name or password is incorrect").pack() #label
        button1 = tk.Button(self.top, text="Ok", width=5, command=self.top.destroy).pack()

        self.top.grab_set() 

#once the user logs in then the menu window is loaded, allowing the user to navigate to the different areas of the program
class Menu(Login): #inheritance
    
    #initialisation creates the different buttons and the school logo
    def __init__(self, parent, controller):
        
        tk.Frame.__init__(self, parent)

        self.controller = controller
        
        self.image = tk.PhotoImage(file="harrislogo.gif") 
        tk.Label(self, image=self.image).grid(row=0, column=1, rowspan=17)

        button1a = tk.Button(self, text='Fixtures and Results', 
                          command=lambda: controller.showFrame(FixRes)) 
        button1a.grid(row=0)

        button2a = tk.Button(self, text='Manage users', command=self.checkAdmin)
        button2a.grid(row=1)
    
        button3a = tk.Button(self, text='Players',
                           command=lambda: controller.showFrame(Players))                         
        button3a.grid(row=2)
    
        button4a = tk.Button(self, text="Sign out", command=self.close) 
        button4a.grid(row=3)

    #if manage users button clicked on, checked to see if admin
    #otherwise error message displayed
    def checkAdmin(self): 
        
        page = self.controller.getPage(Login) #instantiation
        CheckAdmin = page.getCheckAdmin()
        if CheckAdmin==1: 
            self.controller.showFrame(Manage)
        else:
            self.adminError()

    #when the user clicks the 'Sign out' button, a message is displayed to confirm their decision to log out 
    def close(self): 
        
        self.top1 = tk.Toplevel() 

        label1a = tk.Label(self.top1, text="Are you sure you want to sign out?").pack()
        button5a = tk.Button(self.top1, text="Cancel", width=5, command=self.top1.destroy).pack(side='left')
        button6a = tk.Button(self.top1, text="Sign out", width=5, command=self.logOut).pack(side='left')
 
        self.top1.grab_set() 

    #if the user chooses to log out thet are returned to login window
    def logOut(self): 
        
        self.top1.destroy()
        page = self.controller.getPage(Login) #instantiation
        CheckAdmin = page.setCheckAdmin(0)
        self.back()

    #returns to the login window
    #base class method, which will be overridden in the subclass, polymorphism
    def back(self): 
        
        self.controller.showFrame(Login) 

    #if the user enters incorrect details, then a error window is displayed
    def adminError(self): 
        
        self.top1a = tk.Toplevel() 

        label3 = tk.Label(self.top1a, text="Access is denied!").pack() 
        button1 = tk.Button(self.top1a, text="Ok", width=5, command=self.top1a.destroy).pack()

        self.top1a.grab_set() 

#if the user selects the 'Fixtures and Results' button in the menu, this window is loaded
#it displays all the fixtures and results and allows the admin to make changes to them
class FixRes(Menu): #inheritance
    #the intialisation creates the fixRes database
    #creates the different widgets of the window
    def __init__(self, parent, controller):
        
        tk.Frame.__init__(self, parent)

        self.controller = controller
                                                                                  
        conn = sqlite3.connect("football.db")
        c = conn.cursor()
        
        #c.execute("""CREATE TABLE fixRes (
        #             fixResID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
        #             date TEXT,
        #             time TEXT,
        #             home TEXT,
        #             score INTEGER,
        #             away TEXT
        #             )""")
 
        conn.commit()
        conn.close()

        frame1 = tk.Frame(self) 
        frame1.pack(fill='both', expand='yes', side='left')

        #creates treeview, which will display the fixtures and results
        self.tree = ttk.Treeview(frame1) 
        self.tree['columns'] = ('Date', 'Time', 'Home', 'Score', 'Away') 
        self.tree['show']='headings' 
        self.tree.pack()

        self.tree.heading('#1', text='Date') 
        self.tree.column('#1', anchor='center', width=100) 
            
        self.tree.heading('#2', text='Time')
        self.tree.column('#2', anchor='center', width=100)
            
        self.tree.heading('#3', text='Home')    
        self.tree.column('#3', anchor='center')
            
        self.tree.heading('#4', text='Score')
        self.tree.column('#4', anchor='center', width=100)
            
        self.tree.heading('#5', text='Away')
        self.tree.column('#5', anchor='center')

        frame2 = tk.Frame(self) 
        frame2.pack(side='top', expand='yes')

        labelb1 = tk.Label(frame2, text="Fixture/result").grid(row=0, column=1)
        
        labelb2 = tk.Label(frame2, text='Date:').grid(row=1, column=0, sticky='w') 
        self.entry_1a = tk.StringVar()
        self.entry_1 = tk.Entry(frame2, textvariable=self.entry_1a)
        self.entry_1.grid(row=1, column=1)

        labelb3 = tk.Label(frame2, text='Time:').grid(row=2, column=0, sticky='w') 
        self.entry_2a = tk.StringVar()
        #creates combobox, which gives the user options to select
        self.Combo = ttk.Combobox(frame2, textvariable=self.entry_2a, width=17, state="readonly") 
        self.Combo.grid(row=2, column=1)
        self.Combo['values'] = ['12:30','15:00','17:00'] 

        labelb4 = tk.Label(frame2, text='Home:').grid(row=3, column=0, sticky='w')
        self.entry_3a = tk.StringVar()
        self.entry_3 = tk.Entry(frame2, textvariable=self.entry_3a)
        self.entry_3.grid(row=3, column=1)

        labelb5 = tk.Label(frame2, text='Score:').grid(row=4, column=0, sticky='w')
        self.entry_4a = tk.StringVar()
        #make combobox read only so user can't add other things
        self.Combo1 = ttk.Combobox(frame2, textvariable=self.entry_4a, width=5, state="readonly") 
        self.Combo1.grid(row=4, column=1, sticky='w')
        self.Combo1['values']=['','0','1','2','3','4','5','6','7','8','9'] 
        
        self.entry_4a1 = tk.StringVar()
        self.Combo2 = ttk.Combobox(frame2, textvariable=self.entry_4a1, width=5, state="readonly")
        self.Combo2.grid(row=4, column=1, sticky='e')
        self.Combo2['values'] = ['','0','1','2','3','4','5','6','7','8','9'] 
        
        labelb6 = tk.Label(frame2, text='Away:').grid(row=5, column=0, sticky='w')
        self.entry_5a = tk.StringVar()
        self.entry_5 = tk.Entry(frame2, textvariable=self.entry_5a)
        self.entry_5.grid(row=5, column=1)        

        frame3 = tk.Frame(self) 
        frame3.pack(side='bottom', expand='yes')

        b1 = tk.Button(frame3 ,width=7, text='Back', command=self.back).pack(side='left') 
        b2 = tk.Button(frame3 ,width=7, text='Delete', command=self.checkAdmin1).pack(side='left') 

        frame4 = tk.Frame(self)
        frame4.pack(side='bottom', expand='yes')

        b3 = tk.Button(frame4 ,width=17, text='Edit fixture/result', command=self.checkAdmin2).pack(side='left') 
        b4 = tk.Button(frame4 ,width=17, text='Add fixture/result', command=self.checkAdmin3).pack(side='left') 
        
        self.load()

    #if the admin is logged in the delete button is accessible
    #otherwise error message displayed
    def checkAdmin1(self): 
        
        page = self.controller.getPage(Login) #instantiation
        CheckAdmin = page.getCheckAdmin()
        
        if CheckAdmin==1: 
            self.checkDel() 
        else:
            self.adminError()

    #if the admin is logged in the edit button is accessible
    #otherwise error message displayed
    def checkAdmin2(self): 
        
        page = self.controller.getPage(Login) #instantiation
        CheckAdmin = page.getCheckAdmin()
        
        if CheckAdmin==1: 
            self.checkEdit() 
        else:
            self.adminError()

    #if the admin is logged in the edit button is accessible
    #otherwise error message displayed
    def checkAdmin3(self): 
        
        page = self.controller.getPage(Login) #instantiation
        CheckAdmin = page.getCheckAdmin()
        
        if CheckAdmin==1: 
            self.addFixRes() 
        else:
            self.adminError()

    #polymorphism, method was used in base class but has been overridden
    #returns to the menu window
    def back(self): 
        
        self.controller.showFrame(Menu) 

    #error checking, to check whether the user has selected an entry, if so then confirmation message is displayed
    def checkEdit(self): 
        
        try: 
            item1 = self.tree.selection()[0] 
            
            self.top4 = tk.Toplevel()
            label7 = tk.Label(self.top4, text="Are you sure you want to edit this fixture/result?").pack()
            
            button1a = tk.Button(self.top4, text='Cancel', width=7, command=self.top4.destroy).pack(side='left') #creates buttons
            button2a = tk.Button(self.top4, text='Edit', width=7, command=self.funcTwo).pack(side='left')
             
            self.top4.grab_set()                                                                   
            self.top4.mainloop()
        except:
            self.errorSelect() 

    #if the user confirms they want to edit a fixture/result, the toplevel window closes and the method run to carry that process out
    def funcTwo(self):  
        
        self.top4.destroy()     
        self.editFixRes() 

    #clears the GUI of entries
    def clearGui(self): 
        
        self.entry_1.delete(0, 'end')
        self.Combo.set('')
        self.entry_3.delete(0, 'end')
        self.Combo1.set('')
        self.Combo2.set('')
        self.entry_5.delete(0, 'end')

    #if the admin has chosen to edit a fixture/result then that is then inserted into the entry boxes, allowed it to be edited
    def editFixRes(self):
        
        item1 = self.tree.selection()[0] 
        
        self.clearGui() 
        
        self.Edate = self.tree.item(item1)['values'][0] 
        self.Etime = self.tree.item(item1)['values'][1]
        self.Ehome = self.tree.item(item1)['values'][2]
        self.Escore = self.tree.item(item1)['values'][3]
        self.Eaway = self.tree.item(item1)['values'][4]

        self.entry_1.insert(0,self.Edate) 

        #this is normally read-only, but the state is changed to allow the entry of values
        self.Combo.configure(state="normal") 
        self.Combo.insert(0,self.Etime)
        self.Combo.configure(state="readonly")
        
        self.entry_3.insert(0,self.Ehome)

        self.Combo1.configure(state="normal")
        self.Combo1.insert(0,str(self.Escore)[0])
        self.Combo1.configure(state="readonly")

        self.Combo2.configure(state="normal")
        self.Combo2.insert(0,str(self.Escore)[2])
        self.Combo2.configure(state="readonly")
        
        self.entry_5.insert(0,self.Eaway)
        
        self.delete() 

    #if the admin tries to add a new fixture/result then error checking will be calculated before it is added to the database
    def addFixRes(self): 
        
        self.Adate = self.entry_1a.get() 
        self.Atime = self.entry_2a.get()   
        self.Ahome = self.entry_3a.get() 
        self.Ascore1 = self.entry_4a.get() 
        self.Ascore2 = self.entry_4a1.get() 
        self.Aaway = self.entry_5a.get() 

        #sees if fixture or result, and changes the format of the score accordingly  
        if self.Ascore1=="" and self.Ascore2=="": 
            self.score=" - "
        else:
            self.score = self.Ascore1+'-'+self.Ascore2

        self.ch = False #if true then date and score is correct
        self.TodayDate = datetime.datetime.today().strftime('%d-%m-%Y')#todays date
        
        #to see if a score is needed depending on it being fixture/result, as fixture has no result      
        try:
            DateAdate = datetime.datetime.strptime(self.Adate,'%d-%m-%Y')          
            if (DateAdate>(datetime.datetime.strptime(self.TodayDate,'%d-%m-%Y'))
               and (self.Ascore1 in ('',' ')) and (self.Ascore2 in ('',' '))):
                self.ch = True
            elif (DateAdate<(datetime.datetime.strptime(self.TodayDate,'%d-%m-%Y'))
               and (self.Ascore1 not in ('',' ')) and (self.Ascore2 not in ('',' '))):
                self.ch = True
            else:
                ()
        except:
            self.ch = False 
        
        #checks if all entries valid, if they are adds to database, if not error message displayed
        if (self.ch==True and not(self.Atime=='') and self.Ahome.replace(" ", "").isalpha()
           and self.Aaway.replace(" ", "").isalpha() and len(self.Adate)==10):
            
            conn = sqlite3.connect("football.db") 
            c = conn.cursor()

            c.execute("""INSERT INTO fixRes(date,time,home,score,away) VALUES(?,?,?,?,?)""", 
                      (self.Adate, self.Atime, self.Ahome.title(), self.score ,self.Aaway.title()))
                        
            conn.commit()
            conn.close()

            self.clearGui() 

            self.load()
        else:
            self.errorOne() 

    #this method deletes selected fixture/result 
    def delete(self): 
        
        conn = sqlite3.connect("football.db")
        c = conn.cursor()

        self.item = self.tree.selection()[0] 

        self.Ddate = self.tree.item(self.item)['values'][0]
        self.Dtime = self.tree.item(self.item)['values'][1] 
        self.Dhome = self.tree.item(self.item)['values'][2]
        self.Dscore = self.tree.item(self.item)['values'][3]
        self.Daway = self.tree.item(self.item)['values'][4]

        self.tree.delete(self.tree.selection())

        c.execute("DELETE FROM fixRes WHERE(date=? and time=? and home=? and score=? and away=?)",
                  (self.Ddate,self.Dtime,self.Dhome,self.Dscore,self.Daway))    

        conn.commit()
        conn.close()
        
        self.load()

    #this method is used to confirm the admin wants to delete a certain fixure/result
    #if fixture/result not selected then an error message is displayed
    def checkDel(self): 
        
        try:
            self.item = self.tree.selection()[0] 
            
            self.top5 = tk.Toplevel()
            label8 = tk.Label(self.top5, text="Are you sure you want to delete this fixture/result?").pack()
            
            self.button3a = tk.Button(self.top5, text='Cancel', width=7, command=self.top5.destroy).pack(side='left') 
            self.button4a = tk.Button(self.top5, text='Delete', width=7, command=self.funcOne).pack(side='left')            
            
            self.top5.grab_set()                                                                             
            self.top5.mainloop()
            
        except: 
            
            self.errorSelect() 

    #if the user chooses to delete a fixture/result then the toplevel window is closed and the delete method run
    def funcOne(self): 
        
        self.top5.destroy()
        self.delete()
    
    #this method gets the values for the fixtures/results from the database which are then displayed in the treeview
    def load(self):
        
        conn = sqlite3.connect("football.db")
        c = conn.cursor()
        
        c.execute("SELECT date,time,home,score,away FROM fixRes")

        self.list1 = [] #list

        #clears treeview
        for i in self.tree.get_children(): 
            self.tree.delete(i)

        #adds database values into list
        for column in c.fetchall(): 
            self.list1.append(column)

        self.list1.sort(key=lambda L: ((datetime.datetime.strptime(L[0], '%d-%m-%Y')),L[1])) #orders treeview by date and time

        #inserts list values into treeview
        #compare time to see if fixture or result
        #changes fixture colour to grey
        for list in self.list1:        
            if list[3]==" - ": 
                self.tree.insert('', 'end',values=(list[0],list[1],list[2],list[3],list[4]),tags=('tag',))
                self.tree.tag_configure('tag', background='light grey') 
            else:
                self.tree.insert('', 'end', values=(list[0],list[1],list[2],list[3],list[4]))
                
        conn.commit()
        conn.close()

    #error message displayed if incorrect values are entered when trying to add a result/fixture
    def errorOne(self): 
        
        self.top2 = tk.Toplevel()
        self.label9 = tk.Label(self.top2, text="""    Invalid input
        Dates must be in the format DD-MM-YYYY,
        Time must be selected from the values given,
        Home and Away can contain only letters,
        A fixture must contain no score,
        A result must contain a score""").grid(row=0, column=0, sticky='w')

        self.button5a = tk.Button(self.top2,text='Ok',width=5,command=self.top2.destroy).grid(row=1, column=0)
        
        self.top2.grab_set()                                                                               
        self.top2.mainloop()

    #error message displayed if the user hasn't selected a fixture/result when clicking a button to make changes
    def errorSelect(self): 
        
        self.top3 = tk.Toplevel()
        self.label11 = tk.Label(self.top3, text="Please select a fixture/result").grid(row=0, column=0, sticky='w')

        self.button6a = tk.Button(self.top3,text='Ok',width=5,command=self.top3.destroy).grid(row=1, column=0)
        
        self.top3.grab_set()                                                                              
        self.top3.mainloop()
                   
#this window is loaded from the menu and can only accessed by the admin
#it displays all the current user in the system and allows the admin to make changes
class Manage(Menu): #inheritance
    
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        self.controller = controller
        
        self.frame1 = tk.Frame(self, bd=10) 
        self.frame1.pack(fill='both', expand='yes', side='left')
 
        scroll = tk.Scrollbar(self.frame1, orient='vertical') 
        self.listboxData = tk.Listbox(self.frame1, width=30,yscrollcommand=scroll.set) 
        self.listboxData.pack(fill='y', side='left')
        scroll.configure(command=self.listboxData.yview)
        scroll.pack(side='left', fill='y')

        self.frame2 = tk.Frame(self)
        self.frame2.pack(side='top', expand='yes')

        self.label_1 = tk.Label(self.frame2, text = "New user").grid(row=0, column=1) 
        
        self.label_2 = tk.Label(self.frame2, text='Forename:').grid(row=1, column=0, sticky='w')
        self.entry_1a = tk.StringVar()
        self.entry_1 = tk.Entry(self.frame2,textvariable=self.entry_1a) 
        self.entry_1.grid(row=1, column=1)
 
        self.label_3 = tk.Label(self.frame2, text='Surname:').grid(row=2, column=0, sticky='w')
        self.entry_2a = tk.StringVar()
        self.entry_2 = tk.Entry(self.frame2,textvariable=self.entry_2a)
        self.entry_2.grid(row=2, column=1)
 
        self.label_4 = tk.Label(self.frame2, text='Username:').grid(row=3, column=0, sticky='w')
        self.entry_3a = tk.StringVar()
        self.entry_3 = tk.Entry(self.frame2,textvariable=self.entry_3a)
        self.entry_3.grid(row=3, column=1)

        #make entry box read only, can't be written to, as the username is generated by the program
        self.entry_3.configure(state="disabled") 
 
        self.label_5 = tk.Label(self.frame2, text='Password:').grid(row=4, column=0, sticky='w')
        self.entry_4a = tk.StringVar()
        self.entry_4 = tk.Entry(self.frame2,textvariable=self.entry_4a)
        self.entry_4.grid(row=4, column=1)             
        
        self.frame3 = tk.Frame(self)
        self.frame3.pack(side='bottom', expand='yes')

        self.button_1 = tk.Button(self.frame3 ,width=7, text='Back', command=self.back).pack(side='left')
        self.button_2 = tk.Button(self.frame3 ,width=7, text='Delete', command=self.checkDel).pack(side='left')       
        self.button_3 = tk.Button(self.frame3 ,width=7, text='Load', command=self.checkLoadEntry).pack(side='left') 
        self.button_4 = tk.Button(self.frame3 ,width=7, text='Add User', command=self.checkEntry).pack(side='left')

        self.entry_1.bind("<Button-1>", self.clearOne) 
        self.entry_2.bind("<Button-1>", self.clearTwo)
        self.entry_4.bind("<Button-1>", self.clearThree)

        #the program creates the username based on the forename and surname, and it is done live
        self.entry_1.bind('<KeyRelease>', self.changeUser) 
        self.entry_2.bind('<KeyRelease>', self.changeUser)

        #hide '.' if by itself, when window first loaded
        if self.entry_3a.get()=='.': 
            self.entry_3.config(show=' ')
        else:
            ()
         
        self.setSelect()

    #returns to menu window
    #polymorphism
    def back(self):
        
        self.controller.showFrame(Menu)

    #change the entry box color from red to white, when the user clicks on the entry box with the error
    def clearOne(self,event):
        
        self.entry_1.config({"background": "white"}) 
        
    def clearTwo(self,event):
        
        self.entry_2.config({"background": "white"})
        
    def clearThree(self,event):
        
        self.entry_4.config({"background": "white"})

    #live creates the username, while the admin types in the forename and surname
    #displays the generated username is the read-only entry box
    def changeUser(self,event): 
        
        self.CreateUsr = (self.entry_1a.get()+'.'+self.entry_2a.get()).lower()
        self.entry_3a.set(self.CreateUsr) 

    #if the admin presses the load button an error check if carried out to see if user selected
    #otherwise error produced
    def checkLoadEntry(self): 
        
        try: 
            self.listboxData.curselection()[0] 
            self.loadEntry() 
        except:
            self.errorUser() 

    #the admin can view the username and password of a selected user
    def loadEntry(self): 
        
        self.top6 = tk.Toplevel() 
        self.top6.geometry("190x70") 

        self.label_6 = tk.Label(self.top6, text="Username:").grid(row=0, column=0, sticky='w')
        self.usernameVar = tk.StringVar()
        self.username = tk.Entry(self.top6, textvariable=self.usernameVar).grid(row=0, column=1, sticky='w')
        
        self.label_7 = tk.Label(self.top6, text="Password:").grid(row=1, column=0, sticky='w')
        self.passwordVar = tk.StringVar()
        self.password = tk.Entry(self.top6, textvariable=self.passwordVar).grid(row=1, column=1, sticky='w')

        self.mbutton = tk.Button(self.top6,text='Ok',width=5,command=self.top6.destroy).grid(row=2, column=1)
        
        conn = sqlite3.connect("football.db") 
        c = conn.cursor()
        
        c.execute("SELECT username,password FROM login WHERE username!='admin' ORDER BY surname")

        self.gridList = [] #2D list
        
              
        #the values from the database are appended into the list
        for column in c.fetchall():
            self.row = []
            for item in column:
               self.row.append(item)
            self.gridList.append(self.row)

        #the user selected is found and their username and password is then displayed
        self.username,self.password = self.gridList[int(self.listboxData.curselection()[0])]
        self.usernameVar.set(self.username)
        self.passwordVar.set(self.password)
                
        conn.commit()
        conn.close()

        self.top6.grab_set()   
        self.top6.mainloop()

    #this method is used to display the listbox of users and is run when a change has been made to the users
    def setSelect(self):
        
        conn = sqlite3.connect("football.db")
        c = conn.cursor()

        c.execute("SELECT forename,surname FROM login WHERE username!='admin' ORDER BY surname") #the names from the login database are selected

        self.gridList1 = [] #list
        
        for column in c.fetchall():
            self.gridList1.append(column[1]+','+column[0])
    
        self.mergeSort(self.gridList1) #sorts list using mergesort algorithm
                
        self.listboxData.delete(0,'end')
        for item in self.gridList1:
            self.listboxData.insert('end', item) 
        
        conn.commit()
        conn.close()

    #error check when deleting a user to see if a user has been selected
    #if a user hasn't been selected an error message is displayed
    def checkDel(self): 
        
        try: 
            self.listboxData.curselection()[0] 
            self.top7 = tk.Toplevel()
            self.top7.geometry("245x50")
            self.label_8 = tk.Label(self.top7, text="Are you sure you want to delete this user?").pack()

            self.mbutton = tk.Button(self.top7,text='Cancel',width=5,command=self.top7.destroy).pack(side='left')
            self.mbutton1 = tk.Button(self.top7,text='Delete',width=5,command=self.functionTwo).pack(side='left')
                    
            self.top7.grab_set()                                                                               
            self.top7.mainloop()
        except: 
            self.errorUser()
                   
    #if the admin confirms the delete then the toplevel is closed and the delete method is run
    def functionTwo(self): 
        
        self.top7.destroy() 
        self.deleteUser()

    #this method deletes the user from display and the database    
    def deleteUser(self): 
        
        self.x = self.listboxData.curselection() 
        self.listboxData.delete(self.x)
            
        conn = sqlite3.connect("football.db") 
        c = conn.cursor()

        c.execute("SELECT userID FROM login WHERE username!='admin' ORDER BY surname")

        self.gridList2 = [] #list

        for item in c.fetchall(): 
            self.gridList2.append(item)

        self.y = self.gridList2[int(self.x[0])] 
        self.z = self.y[0]
 
        c.execute("DELETE FROM login WHERE userID=?",(self.z,)) 
        
        conn.commit()
        conn.close()
                   
    #error checking for adding a new user checks the forename, surname and passwor
    #if there is an error and error message is produced and the incorrect entry boxes are highlighted red
    #to check password, made use of regular expressions
    def checkEntry(self): 
        
        fname = self.entry_1a.get() #checks if forename contains only letters
        sname = self.entry_2a.get() #checks if surname contains only letters
        psswrd = re.match("((?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!£$%&*@~#?+]).{8,})",self.entry_4a.get()) #regular expression

        #correct input, method run to add details
        if fname.isalpha() and sname.isalpha() and psswrd:
            self.addUser()

        #the forename is incorrect                   
        elif not(fname.isalpha()) and sname.isalpha() and psswrd: 
            self.entry_1.config({"background": "red"})
            self.userError() 

        #the surname is incorrect                                 
        elif fname.isalpha() and not(sname.isalpha()) and psswrd: 
            self.entry_2.config({"background": "red"})
            self.userError()

        #the password is incorrect                                                                             
        elif fname.isalpha() and sname.isalpha() and not(psswrd): 
            self.entry_4.config({"background": "red"})
            self.passwordError()

        #the surname and password are incorrect
        elif fname.isalpha() and not(sname.isalpha()) and not(psswrd): 
            self.entry_2.config({"background": "red"})
            self.entry_4.config({"background": "red"})
            self.userPassError()                                                                               

        #the forename and password are incorrect 
        elif not(fname.isalpha()) and sname.isalpha() and not(psswrd): 
            self.entry_1.config({"background": "red"})
            self.entry_4.config({"background": "red"})
            self.userPassError()                                                                              

        #the forename and password are incorrect
        elif not(fname.isalpha()) and not(sname.isalpha()) and (psswrd): 
            self.entry_1.config({"background": "red"})
            self.entry_2.config({"background": "red"})
            self.userError()
                   
        #everything is incorrect
        else:
            self.entry_1.config({"background": "red"})
            self.entry_2.config({"background": "red"})
            self.entry_4.config({"background": "red"})
            self.userPassError()                                                                              

    #if the correct details have been entered then the user is added to display and the database
    def addUser(self): 
               
        self.y = (self.entry_1a.get())+'.'+(self.entry_2a.get()) 
        firstName = self.entry_1a.get().lower().title()
        lastName = self.entry_2a.get().lower().title()

        conn = sqlite3.connect("football.db") 
        c = conn.cursor()
        
        c.execute("INSERT INTO login(forename,surname,username,password) VALUES(?,?,?,?)",
                  (firstName, lastName, self.y, self.entry_4a.get()))
        
        conn.commit()
        conn.close()

        self.entry_1.delete(0, 'end')
        self.entry_2.delete(0, 'end')
        
        self.entry_3.configure(state="normal")
        self.entry_3.delete(0, 'end')
        self.entry_3.configure(state="disabled")
        
        self.entry_4.delete(0, 'end')

        self.setSelect() 

    #merge sort, recursive algorithm, sorts any list passed
    def mergeSort(self,listInput): 
        if len(listInput)>1:
            mid = len(listInput)//2
            left = listInput[:mid]
            right = listInput[mid:]

            self.mergeSort(left)
            self.mergeSort(right)

            x = 0
            y = 0
            z = 0
            
            while x < len(left) and y < len(right):
                if left[x] < right[y]:
                    listInput[z] = left[x]
                    x+=1
                else:
                    listInput[z] = right[y]
                    y+=1
                z+=1

            while x < len(left):
                listInput[z] = left[x]
                x+=1
                z+=1

            while y < len(right):
                listInput[z] = right[y]
                y+=1
                z+=1

    #error message incorrect username
    def userError(self): 
        self.top8 = tk.Toplevel()
        
        self.label_9 = tk.Label(self.top8, text="""Names must contain letters only,no special characters or numbers and at least 1 letter
        """).grid(row=0, column=0, sticky='w')
        self.mbutton = tk.Button(self.top8,text='Ok',width=5,command=self.top8.destroy).grid(row=1, column=0)
        
        self.top8.grab_set()                                                                               
        self.top8.mainloop()

    #error message incorrect password
    def passwordError(self):
        self.top9 = tk.Toplevel()
        
        self.label_10 = tk.Label(self.top9, text="""Password must contain at least 8 characters, include UPPER/lowercase, numbers and special characters
        """).grid(row=0, column=0, sticky='w')
        self.mbutton = tk.Button(self.top9,text='Ok',width=5,command=self.top9.destroy).grid(row=1, column=0)
        
        self.top9.grab_set()                                                                               
        self.top9.mainloop()

    #error message incorrect username and password
    def userPassError(self):          
        self.top10 = tk.Toplevel()
        
        self.label_11 = tk.Label(self.top10, text="""
        Password must contain at least 8 characters, include UPPER/lowercase, numbers and special characters
        Names must contain letters only,no special characters or numbers and at least 1 letter""").grid(row=0, column=0, sticky='w')

        self.mbutton = tk.Button(self.top10,text='Ok',width=5,command=self.top10.destroy).grid(row=1, column=0)
        
        self.top10.grab_set()                                                                                  
        self.top10.mainloop()

    #error message, user not selected
    def errorUser(self):   
        self.top11 = tk.Toplevel()
        self.label_12 = tk.Label(self.top11, text="Please select a user").grid(row=0, column=0, sticky='w')

        self.mbutton1 = tk.Button(self.top11,text='Ok',width=5,command=self.top11.destroy).grid(row=1, column=0)
        
        self.top11.grab_set() #make sure you can't click away                                                                                
        self.top11.mainloop()

#this window displays the player information, where only the admin can save changes
class Players(Menu): #inheritance
    #initialisation creates player database and the widgets for the window
    def __init__(self, parent, controller):
        
        tk.Frame.__init__(self, parent)
    
        self.controller = controller

        conn = sqlite3.connect("football.db") 
        conn.execute('pragma foreign_keys=ON') #enable foreign key
        c = conn.cursor()   

        #c.execute("""CREATE TABLE player(
        #           playerID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
        #           userID INTEGER,
        #           dob TEXT,
        #           height INTEGAR,
        #           weight INTEGAR,
        #           position TEXT,
        #           appearances INTEGAR,
        #           goals INTEGAR,
        #           assists INTEGAR,
        #           yellow_cards INTEGAR,
        #           red_cards INTEGAR,
        #           FOREIGN KEY(userID) REFERENCES login(userID)
        #           )""")
        
        self.frame5 = tk.Frame(self) 
        self.frame5.pack(side='left')
 
        scrolla = tk.Scrollbar(self.frame5, orient='vertical') 
        self.listboxData = tk.Listbox(self.frame5, width=30, height=16,yscrollcommand=scrolla.set)
        self.listboxData.pack(fill='y', side='left')
        scrolla.configure(command=self.listboxData.yview) 
        scrolla.pack(side='left', fill='y')

        self.note = ttk.Notebook(self) #create notebook widget
        self.note.pack()

        self.framea1 = tk.Frame(self.note)
        self.framea2 = tk.Frame(self.note)
        self.note.add(self.framea2, text='Overview') #adds the two tabs on the notebook, Overview and Information
        self.note.add(self.framea1, text='Information')

        self.image1 = tk.PhotoImage(file="dp.gif") 
        tk.Label(self.framea2,image=self.image1).grid(row=0,column=1)

        self.label_a1 = tk.Label(self.framea2, text='Name:').grid(row=2, column=1, sticky='w') 
        self.label_a2 = tk.Label(self.framea2, text='Position:').grid(row=3, column=1, sticky='w')
        self.label_a3 = tk.Label(self.framea2, text='Nationality:').grid(row=4, column=1, sticky='w')
        
        self.label_1 = tk.Label(self.framea1, text='Name:').grid(row=1, column=0, sticky='w')
        self.entry_1a = tk.StringVar()
        self.entry_1 = tk.Entry(self.framea1,textvariable=self.entry_1a)
        self.entry_1.grid(row=1, column=1)
        self.entry_1.configure(state="disabled") 

        self.label_2 = tk.Label(self.framea1, text='Date of birth:').grid(row=2, column=0, sticky='w') 
        self.entry_2a = tk.StringVar()
        self.entry_2 = tk.Entry(self.framea1,textvariable=self.entry_2a)
        self.entry_2.grid(row=2, column=1)

        self.label_3 = tk.Label(self.framea1, text='Height(cm):').grid(row=3, column=0, sticky='w')
        self.entry_3a = tk.StringVar()
        self.entry_3 = tk.Entry(self.framea1,textvariable=self.entry_3a)
        self.entry_3.grid(row=3, column=1)

        self.label_4 = tk.Label(self.framea1, text='Weight(kg):').grid(row=4, column=0, sticky='w')
        self.entry_4a = tk.StringVar()
        self.entry_4 = tk.Entry(self.framea1,textvariable=self.entry_4a)
        self.entry_4.grid(row=4, column=1)

        self.labelc = tk.Label(self.framea1, text='Position:').grid(row=5, column=0, sticky='w')
        self.entry_c = tk.StringVar()  
        self.Combo = ttk.Combobox(self.framea1,textvariable=self.entry_c,width=17,state="readonly") 
        self.Combo.grid(row=5, column=1)
        self.Combo['values']=['Goalkeeper','Defender','Midfielder','Forward'] 

        self.label_5 = tk.Label(self.framea1, text='Appearance(s):').grid(row=6, column=0, sticky='w')
        self.entry_5a = tk.StringVar()
        self.entry_5 = tk.Entry(self.framea1,textvariable=self.entry_5a)
        self.entry_5.grid(row=6, column=1)

        self.label_6 = tk.Label(self.framea1, text='Goal(s):').grid(row=7, column=0, sticky='w')
        self.entry_6a = tk.StringVar()
        self.entry_6 = tk.Entry(self.framea1,textvariable=self.entry_6a)
        self.entry_6.grid(row=7, column=1)

        self.label_7 = tk.Label(self.framea1, text='Assist(s):').grid(row=8, column=0, sticky='w')
        self.entry_7a = tk.StringVar()
        self.entry_7 = tk.Entry(self.framea1,textvariable=self.entry_7a)
        self.entry_7.grid(row=8, column=1)

        self.label_8 = tk.Label(self.framea1, text='Yellow card(s):').grid(row=9, column=0, sticky='w')
        self.entry_8a = tk.StringVar()
        self.entry_8 = tk.Entry(self.framea1,textvariable=self.entry_8a)
        self.entry_8.grid(row=9, column=1)

        self.label_9 = tk.Label(self.framea1, text='Red card(s):').grid(row=10, column=0, sticky='w')
        self.entry_9a = tk.StringVar()
        self.entry_9 = tk.Entry(self.framea1,textvariable=self.entry_9a)
        self.entry_9.grid(row=10, column=1)

        self.frame1d = tk.Frame(self) 
        self.frame1d.pack(side='left')
        
        self.backButton = tk.Button(self.frame1d, width=7, text='Back', command=self.back).pack(side='left')
        self.backButton1 = tk.Button(self.frame1d, width=7, text='Clear', command=self.clearEntry).pack(side='left')
        self.backButton2 = tk.Button(self.frame1d, width=7, text='Edit/View', command=self.checkUserEdit).pack(side='left')
        self.backButton3 = tk.Button(self.frame1d, width=7, text='Add', command=self.checkAdmin).pack(side='left')

        self.listboxData.bind('<Double-Button-1>', self.overview) #if you double click listbox entry, method run

        self.mainSelect()

        conn.commit()
        conn.close()

    #checks if admin logged in
    #if so add button accessible
    #otherwise error message
    def checkAdmin(self):
        
        page = self.controller.getPage(Login) #instantiation
        CheckAdmin = page.getCheckAdmin()
        if CheckAdmin==1: 
            self.addPlayer()
        else:
            self.adminError()

    #return to menu window
    def back(self): #polymorphism
        
        self.controller.showFrame(Menu) 

    #error check when editing/viewing a user to see if a user has been selected
    def checkUserEdit(self): 
        
        try:
            self.listboxData.curselection()[0] 
     
            self.top12 = tk.Toplevel()
            self.label7 = tk.Label(self.top12, text="Are you sure you want to Edit/View this player's information").pack()
            
            self.mbutton1 = tk.Button(self.top12, text='Cancel', width=7, command=self.top12.destroy).pack(side='left')
            self.mbutton = tk.Button(self.top12, text='Edit/View', width=7, command=self.funcThree).pack(side='left')
                      
            self.top12.grab_set()                                                                            
            self.top12.mainloop()

        except:
            page = self.controller.getPage(Manage) #instantiation
            page.errorUser()

    #closes toplevel window and loads edit method
    def funcThree(self):
        
        self.top12.destroy() 
        self.loadName() 

    #overview window on notebook
    #displays name, nationality and position, if there is one, of selected user
    def overview(self,event): 
        self.displayUsr = self.gridList4[int(self.listboxData.curselection()[0])] 
        self.userSelect = self.userList[int(self.listboxData.curselection()[0])]
                
        self.var = tk.StringVar() 
        self.label_a4 = tk.Label(self.framea2,text="                             ").grid(row=2, column=2, sticky='w')
        self.label_a4 = tk.Label(self.framea2,textvariable=self.var).grid(row=2, column=2, sticky='w')
        self.var.set(self.displayUsr)
        self.label_a5 = tk.Label(self.framea2,text="English").grid(row=4, column=2, sticky='w') 
        
        #displays position of user if there is one
        try: 
            conn = sqlite3.connect("football.db")
            c = conn.cursor()

            #cross-table parameterised SQL statement
            c.execute("""SELECT player.position
                      FROM login
                      INNER JOIN player
                      ON login.userID=player.userID
                      WHERE login.username=?""",(self.userSelect,))

            self.var1 = tk.StringVar()
            self.label_a5 = tk.Label(self.framea2, text="                    ").grid(row=3, column=2, sticky='w')
            self.label_a5 = tk.Label(self.framea2, textvariable=self.var1).grid(row=3, column=2, sticky='w') 
            self.var1.set(c.fetchall())

            conn.commit()
            conn.close()
                
        except:
            ()        

    #this is used when editing or viewing a player's information, it displays the information
    def loadName(self): 
        
        self.clearEntry()
                   
        self.usrName = self.gridList4[int(self.listboxData.curselection()[0])]
        self.userSelect = self.userList[int(self.listboxData.curselection()[0])]
        self.entry_1a.set(self.usrName)

        conn = sqlite3.connect("football.db")
        c = conn.cursor()

        c.execute("SELECT userID FROM login WHERE username=?",(self.userSelect,))
        self.userID = c.fetchall()[0][0]

        #cross-table parameterised SQL statement
        c.execute("""SELECT player.dob,player.height,player.weight,player.position,player.appearances,
                  player.goals,player.assists,player.yellow_cards,player.red_cards
                  FROM login
                  INNER JOIN player
                  ON login.userID=player.userID
                  WHERE login.username=?""",(self.userSelect,))

        self.gridList3 = []#2D list

        #appends the selected value from the database into the list
        for column in c.fetchall(): 
            self.row = []
            for item in column:
                self.row.append(item)
            self.gridList3.append(self.row)

        #try and insert database values into the GUI, if the user has any data
        try: 

            self.entry_2.insert(0,self.gridList3[0][0])
            self.entry_3.insert(0,self.gridList3[0][1])
            self.entry_4.insert(0,self.gridList3[0][2])
            
            self.Combo.configure(state="normal")
            self.Combo.insert(0,self.gridList3[0][3])
            self.Combo.configure(state="readonly")
            
            self.entry_5.insert(0,self.gridList3[0][4])
            self.entry_6.insert(0,self.gridList3[0][5])
            self.entry_7.insert(0,self.gridList3[0][6])
            self.entry_8.insert(0,self.gridList3[0][7])
            self.entry_9.insert(0,self.gridList3[0][8])
        except:
            ()
        
        conn.commit()
        conn.close()
            
    def addPlayer(self):
        
        self.name = self.entry_1.get() 
        self.dob = self.entry_2.get() 
        self.height = self.entry_3.get() 
        self.weight = self.entry_4.get() 
        self.pos = self.entry_c.get() 
        self.appear = self.entry_5.get() 
        self.goal = self.entry_6.get() 
        self.assist = self.entry_7.get() 
        self.ycards = self.entry_8.get() 
        self.rcards = self.entry_9.get() 
           
        self.ch = False
        self.TodayDate = datetime.datetime.today().strftime('%d-%m-%Y') #todays date
        
        #the date entered is checked to make sure it is before today's date
        try:
            dateDate = datetime.datetime.strptime(self.dob,'%d-%m-%Y') 
            if dateDate<(datetime.datetime.strptime(self.TodayDate,'%d-%m-%Y')) and len(self.dob)==10:
                self.ch = True
            else:        
                ()
        except:
            self.ch = False

        conn = sqlite3.connect("football.db")
        c = conn.cursor()
        
        #all the data values are checked, makes sure there only number values entered    
        if (self.pos!='' and (self.name!='')and self.ch==True and self.height.isdigit() and self.weight.isdigit() and self.appear.isdigit()
           and self.goal.isdigit() and self.assist.isdigit() and self.ycards.isdigit() and self.rcards.isdigit()):
            
            conn = sqlite3.connect("football.db")
            c = conn.cursor()

            c.execute("SELECT userID from Player")
            
            if str(self.userID) in str(c.fetchall()):
                c.execute("""UPDATE player SET dob=?,height=?,weight=?, position=?,appearances=?,
                           goals=?,assists=?,yellow_cards=?,red_cards=? WHERE userID=?""",
                          (self.dob,self.height,self.weight,self.pos,self.appear,self.goal,self.assist,self.ycards,self.rcards,self.userID))
             
            else:
                c.execute("""INSERT INTO player(userID,dob,height,weight,position,appearances,goals,assists,yellow_cards,red_cards)
                          VALUES(?,?,?,?,?,?,?,?,?,?)""",
                         (self.userID,self.dob,self.height,self.weight,self.pos,self.appear,self.goal,self.assist,self.ycards,self.rcards))
                               
            conn.commit()
            conn.close()

            self.clearEntry()
                   
            self.mainSelect()
        else:
            self.inputError() 

    #displays the listbox data, the different players
    def mainSelect(self):
        conn = sqlite3.connect("football.db")
        c = conn.cursor()

        c.execute("SELECT forename,surname,username FROM login WHERE username!=? ORDER BY surname",("admin",))

        self.gridList4 = [] #list
        self.userList = []
        
        for column in c.fetchall():
            self.gridList4.append(column[1]+','+column[0])
            self.userList.append(column[2])

        page = self.controller.getPage(Manage) #instantiation, to run the mergesort algorithm used previously in another class
        page.mergeSort(self.gridList4) #the list is passed, to make put it in order
          
        self.listboxData.delete(0,'end') 
        for item in self.gridList4:      
            self.listboxData.insert('end', item) 

        conn.commit()
        conn.close()
                   
    #this method clears the GUI by deleting all the entry box values
    def clearEntry(self): 
        
        self.entry_1.configure(state="normal")
        self.entry_1.delete(0, 'end')
        self.entry_1.configure(state="disabled")
        self.entry_2.delete(0, 'end')
        self.entry_3.delete(0, 'end')
        self.entry_4.delete(0, 'end')
        
        self.Combo.set('')
        
        self.entry_5.delete(0, 'end')
        self.entry_6.delete(0, 'end')
        self.entry_7.delete(0, 'end')
        self.entry_8.delete(0, 'end')
        self.entry_9.delete(0, 'end')

    #this error message is produced if the admin enters incorrect values for the player information
    def inputError(self): 
        
        self.top14 = tk.Toplevel()
        self.label9 = tk.Label(self.top14, text="""Invalid input
        You must select a name from the list,
        Dates must be in the format DD-MM-YYYY,
        All of the other entries must be positive whole numbers""").grid(row=0, column=0, sticky='w')

        self.mbutton = tk.Button(self.top14,text='Ok',width=5,command=self.top14.destroy).grid(row=1, column=0)
        
        self.top14.grab_set()                                                                            
        self.top14.mainloop()

    
app = Start()
app.mainloop()                                         

This snippet took 0.09 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).