Python Forum
Current project - Simple tkinter login system
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Current project - Simple tkinter login system
#1
Just a simple login system. It's not complete, still have some details to work on and after maybe make a generic page class as I have some repeating code.

# Do the imports
import tkinter as tk
from tkinter import font
import sqlite3 as sq
import os


# Executed from bash shell or vscode - vscode default
path = os.path.dirname(os.sys.argv[0])
if not path:
    path = '.'

class Database:
    '''
    Database class handles all methods for the adding, deleting, and retrieving
    information
    '''
    def __init__(self):
        ''' Setup the sqlite3 database and cursor '''
        self.db = sq.connect(f'{path}/customer.db')
        self.cursor = self.db.cursor()

    def create(self):
        ''' create creates the table and sets up a basic email validation '''
        query = '''
                create table if not exists customer (
                id integer primary key,
                name text not null,
                email text unique not null,
                password text not null,
                logged_in integer not null default 0
                check(
                    email like '%_@_%._%' and
                    length(email) - length(replace(email, '@', '')) = 1 and
                    substr(lower(email), 1, instr(email, '.') - 1) not glob '*[^@0-9a-z]*' and
                    substr(lower(email), instr(email, '.') + 1) not glob '*[^a-z]*'
                    ))
                '''
        # Execute and commit the query
        self.db.execute(query)
        self.db.commit()

    def add(self, name, email, password):
        ''' Method add data to the database and handles some error checking '''       
        query = '''
                insert into customer (name, email, password) values (?,?,?)
                '''
        try:
            self.cursor.execute(query, (name.lower().strip(), email.lower().strip(), password))
            self.db.commit()
            return ' Added user to database.'
        except sq.OperationalError as error:
            return error
        except sq.IntegrityError as error:
            if 'constraint' in str(error) and 'customer.email' in str(error):
                return 'That email already exists. Please try again.'
            elif 'CHECK' in str(error):
                return 'That is not a valid email. Please try again.'
            else:
                return 'An unknown error has occurred'
            
    def remove(self, id):
        ''' Method for removing users by id '''
        if id:
            self.cursor.execute(f'delete from customer where id = {id}')

    def getall(self):
        ''' Method gets all information from database '''
        return self.cursor.execute('select * from customer').fetchall()
    
    def getone(self, id):
        ''' Method gets information for a single id '''
        if id:
            return self.cursor.execute(f'select * from customer where id = {id}').fetchone()
        
    def login(self, email, password):
        ''' Method checks if a user is in the database based on email and password 
            if a user is found then it will set a session variable for being logged in.
        '''
        query = f'''
                select id, email, password from customer where email = "{email}" and password = "{password}"
                '''
        res = self.cursor.execute(query).fetchone()
        if res:
            self.update(res[0], 1)
            return True
        return False
    
    def update(self, id, log=int(0)):
        ''' Helper method for above method. Set the logged_in field to 1 '''
        self.cursor.execute(f'update customer set logged_in = {log} where id = {id}')

    def logout(self, id, log=int(0)):
        ''' Method for logging out. Sets the logged_in field to 0 '''
        self.cursor.execute(f'update customer set logged_in = {log} where id = {id}')


class Window:
    '''
    Window class is the main display window
    '''
    def __init__(self, parent):
        self.parent = parent
        parent.title('Main Page')
        parent.columnconfigure(0, weight=1)
        parent.rowconfigure(0, weight=1)

        parent.update()
        width = parent.winfo_reqwidth() * 3

        # Container frame for holding all widgets
        container = tk.Frame(parent, bg='#555555')
        container.grid(column=0, row=0, sticky='news')
        container.grid_columnconfigure(0, weight=3)

        # Simple header label
        header = tk.Label(container, text='Main Page')
        header['font'] = ('cursive', 30, 'bold')
        header['bg'] = '#333333'
        header['fg'] = 'whitesmoke'
        header['relief'] = 'solid'
        header['borderwidth'] = 1
        header.grid(column=0, row=0, sticky='new', ipady=10)

        # The container holds all our links
        link_container = tk.Frame(container, bg='white')
        link_container.grid(column=0, row=1, sticky='new')
        
        # Create our links using labels. Bind links to give a hover effect
        self.login_label = tk.Label(link_container, text='Login', fg='blue', bg='white', cursor='hand2')
        self.login_label['font'] = (None, 12, 'normal')
        self.login_label.grid(column=0, row=0, padx=5, pady=5)
        self.login_label.bind('<Enter>', lambda label: self.link_on(self.login_label))
        self.login_label.bind('<Leave>', lambda label: self.link_off(self.login_label))

        self.logout_label = tk.Label(link_container, text='Logout', fg='blue', bg='white', cursor='hand2')
        self.logout_label['font'] = (None, 12, 'normal')
        self.logout_label.grid(column=1, row=0, padx=5, pady=5)
        self.logout_label.bind('<Enter>', lambda label: self.link_on(self.logout_label))
        self.logout_label.bind('<Leave>', lambda label: self.link_off(self.logout_label))


        self.register_label = tk.Label(link_container, text='Register', fg='blue', bg='white', cursor='hand2')
        self.register_label['font'] = (None, 12, 'normal')
        self.register_label.grid(column=2, row=0, padx=5, pady=5)
        self.register_label.bind('<Enter>', lambda label: self.link_on(self.register_label))
        self.register_label.bind('<Leave>', lambda label: self.link_off(self.register_label))


        self.exit_label = tk.Label(link_container, text='Exit', fg='tomato', bg='white', cursor='hand2')
        self.exit_label['font'] = (None, 14, 'normal')
        self.exit_label.grid(column=3, row=0, padx=(width,10), pady=5)
        self.exit_label.bind('<Enter>', self.exit_enter)
        self.exit_label.bind('<Leave>', self.exit_leave)

        self.log = tk.Label(container, text='Your are logged out', bg='#555555', fg='#cecece', anchor='e', padx=5)
        self.log['font'] = (None, 12, 'bold')
        self.log.grid(column=0, row=2, padx=5, pady=5, sticky='new')

    # These methods provide the hover effects
    def link_on(self, label):
        label['fg'] = 'orangered'

    def link_off(self, label):
        label['fg'] = 'blue'

    def exit_enter(self, event):
        self.exit_label['fg'] = 'red'

    def exit_leave(self, event):
        self.exit_label['fg'] = 'tomato'


class LoginForm:
    ''' This class contains our login form'''
    def __init__(self, parent):
        self.parent = parent

    def form(self):
        self.window = tk.Toplevel(None)
        self.window.minsize(800,600)
        self.window['padx'] = 3
        self.window['pady'] = 3
        self.window.title('A Login Form')
        self.window.columnconfigure(0, weight=1)
        self.window.rowconfigure(0, weight=1)
        self.window['bg'] = '#333333'

        container = tk.Label(self.window, bg='#555555')
        container.grid(column=0, row=0, sticky='news')
        container.grid_columnconfigure(0, weight=3)

        # Simple header label
        header = tk.Label(container, text='Login Page')
        header['font'] = ('cursive', 30, 'bold')
        header['bg'] = '#333333'
        header['fg'] = 'whitesmoke'
        header['relief'] = 'solid'
        header['borderwidth'] = 1
        header.grid(column=0, row=0, sticky='new', ipady=10)

        self.button = tk.Button(self.window, text='Cancel', bg='tomato', fg='black', cursor='hand2')
        self.button['font'] = (None, 12, 'normal')
        self.button['command'] = self.close
        self.button['highlightbackground'] = 'black'
        self.button['highlightcolor'] = 'black'
        self.button.grid(column=0, row=1)
        self.button.bind('<Enter>', self.on_enter)
        
    def close(self):
        ''' Method for destroying the form window and retreiving the main window '''
        self.window.destroy()
        self.parent.deiconify()

    def on_enter(self, event):
        # method for hover effect of the cancel button
        self.button['activebackground'] = 'orangered'
        self.button['activeforeground'] = 'white'


class RegisterForm:
    ''' This class contains the registraion form '''
    def __init__(self, parent):
        self.parent = parent

    def form(self):
        self.window = tk.Toplevel(None)
        self.window.minsize(800,600)
        self.window['padx'] = 3
        self.window['pady'] = 3
        self.window.title('Registation Form')
        self.window.columnconfigure(0, weight=1)
        self.window.rowconfigure(0, weight=1)
        self.window['bg'] = '#333333'

        container = tk.Label(self.window, bg='#555555')
        container.grid(column=0, row=0, sticky='news')
        container.grid_columnconfigure(0, weight=3)

        # Simple header label
        header = tk.Label(container, text='Registration Page')
        header['font'] = ('cursive', 30, 'bold')
        header['bg'] = '#333333'
        header['fg'] = 'whitesmoke'
        header['relief'] = 'solid'
        header['borderwidth'] = 1
        header.grid(column=0, row=0, sticky='new', ipady=10)

        self.button = tk.Button(self.window, text='Cancel', bg='tomato', fg='black', cursor='hand2')
        self.button['font'] = (None, 12, 'normal')
        self.button['command'] = self.close
        self.button['highlightbackground'] = 'black'
        self.button['highlightcolor'] = 'black'
        self.button.grid(column=0, row=1)
        self.button.bind('<Enter>', self.on_enter)
        
    def close(self):
        ''' Method for destroying the form window and retreiving the main window '''
        self.window.destroy()
        self.parent.deiconify()

    def on_enter(self, event):
        # method for hover effect of the cancel button
        self.button['activebackground'] = 'orangered'
        self.button['activeforeground'] = 'white'




    def update(self):
        pass


class Controller:
    '''
    Controller class will handle all communications between the other classes
    '''
    def __init__(self, db, window, loginform, registerform):
        # setup some class variables
        self.db = db
        self.window = window
        self.loginform = loginform
        self.registerform = registerform
        self.session = 0

        # Window Link Commands
        self.window.login_label.bind('<Button-1>', lambda event: self.login())
        self.window.logout_label.bind('<Button-1>', lambda event: self.logout())
        self.window.register_label.bind('<Button-1>', lambda event: self.register())
        self.window.exit_label.bind('<Button-1>', lambda event: self.window_exit())

    def login(self):
        ''' Method for getting the login form '''
        self.window.parent.withdraw()
        self.loginform.form()
        self.window.log['text'] = 'Your logged in'
        self.window.log['fg'] = 'whitesmoke'

    def logout(self):
        ''' Method for logging out '''
        self.db.logout(1)
        self.window.log['text'] = 'Your logged out'
        self.window.log['fg'] = '#cecece'

    def register(self):
        ''' Method for registering new user '''
        self.window.parent.withdraw()
        self.registerform.form()

    def window_exit(self):
        ''' Method will log out user and exit program '''
        self.db.logout(1)
        self.window.parent.destroy()


if __name__ == '__main__':
    root = tk.Tk()
    root.minsize(800, 600)
    root['padx'] = 3
    root['pady'] = 3
    controller = Controller(Database(), Window(root), LoginForm(root), RegisterForm(root))
    root.mainloop()
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#2
this is amazing and good try to use tkinter library. thanks for the sharing the code. before some days ago. i also used tkinter python library to develop WordPress Post Creator. It is working amazing also. i share you screenshot below.

[Image: WordPress-Post-Creator-Screentshot-2-e16...52287.webp]
Reply
#3
(Aug-29-2023, 08:31 AM)ahmedd Wrote: this is amazing and good try to use tkinter library. thanks for the sharing the code. before some days ago. i also used tkinter python library to develop WordPress Post Creator. It is working amazing also. i share you screenshot below.

[Image: WordPress-Post-Creator-Screentshot-2-e16...52287.webp]
Reply
#4
Here is the finished script. Might still have a bug or two that I've not caught. Doesn't really do anything. Registers a user, logs in a user and displays a message for logged in user, and will logout a user. Nothing fancy.

import tkinter as tk
import sqlite3 as sq
import os
import webbrowser

# Executed from bash shell or vscode - vscode is default
path = os.path.dirname(os.sys.argv[0])
if not path:
    path = '.'

class Database:
    '''
    Database class handles all methods for the adding, deleting, and retrieving
    information
    '''
    def __init__(self):
        ''' Setup the sqlite3 database and cursor '''
        self.db = sq.connect(f'{path}/customer.db')
        self.cursor = self.db.cursor()

    def create(self):
        ''' create creates the table and sets up a basic email validation '''
        query = '''
                create table if not exists customer (
                id integer primary key,
                name text not null,
                email text unique not null,
                password text not null,
                logged_in integer not null default 0
                check(
                    email like '%_@_%._%' and
                    length(email) - length(replace(email, '@', '')) = 1 and
                    substr(lower(email), 1, instr(email, '.') - 1) not glob '*[^@0-9a-z]*' and
                    substr(lower(email), instr(email, '.') + 1) not glob '*[^a-z]*'
                    ))
                '''
        # Execute and commit the query
        self.db.execute(query)
        self.db.commit()

    def register(self, name, email, password):
        ''' Method add data to the database and handles some error checking '''       
        query = '''
                insert into customer (name, email, password) values (?,?,?)
                '''

        self.cursor.execute(query, (name.lower().strip(), email.lower().strip(), password))
        self.db.commit()
            
    def remove(self, id):
        ''' Method for removing users by id '''
        if id:
            self.cursor.execute(f'delete from customer where id = {id}')

    def getall(self):
        ''' Method gets all information from database '''
        return self.cursor.execute('select * from customer').fetchall()
    
    def getone(self, id):
        ''' Method gets information for a single id '''
        if id:
            return self.cursor.execute(f'select * from customer where id = {id}').fetchone()
        
    def login(self, email, password):
        ''' Method checks if a user is in the database based on email and password 
            if a user is found then it will set a session variable for being logged in.
        '''
        query = f'''
                select id, email, password from customer where email = "{email}" and password = "{password}"
                '''
        res = self.cursor.execute(query).fetchone()
        if res:
            return True
        return False
    

class Window:
    '''
    Window class is the main display window
    '''
    def __init__(self, parent):
        self.parent = parent
        self.parent.minsize(800,600)
        parent.title('Main Page')
        parent.columnconfigure(0, weight=1)
        parent.rowconfigure(0, weight=1)

        # Container frame for holding all widgets
        container = tk.Frame(parent, bg='#555555')
        container.grid(column=0, row=0, sticky='news', padx=5, pady=5)
        container.grid_columnconfigure(0, weight=3)
        container.grid_rowconfigure(2, weight=3)

        # Link container to hold various link frames
        linksframe = tk.Frame(container, bg='white')
        linksframe.grid(column=0, row=1, sticky='new')
        linksframe.grid_columnconfigure(0, weight=0)
        linksframe.grid_columnconfigure(1, weight=3)
        linksframe.grid_columnconfigure(2, weight=3)

        links = tk.Frame(linksframe, bg='white')
        links.grid(column=0, row=0, sticky='new')

        # Admin container will show when logged in
        self.adminframe =tk.Frame(linksframe, bg='white')
        self.adminframe.grid(column=1, row=0, sticky='new')
        self.adminframe.grid_columnconfigure(0, weight=3)

        # Footer Frame
        footerframe = tk.Frame(container, bg='#333333')
        footerframe.grid(column=0, row=2, sticky='sew')
        footerframe.grid_columnconfigure(0, weight=3)

        # Simple header label
        header = tk.Label(container, text='Main Page')
        header['font'] = ('cursive', 30, 'bold')
        header['bg'] = '#333333'
        header['fg'] = 'whitesmoke'
        header['relief'] = 'solid'
        header['borderwidth'] = 1
        header.grid(column=0, row=0, sticky='new', ipady=10)

        # Create our links using labels. Bind links to give a hover effect
        self.login_label = tk.Label(links, text='Login', fg='blue', bg='white', cursor='hand2')
        self.login_label['font'] = (None, 12, 'normal')
        self.login_label.grid(column=0, row=0, padx=5, pady=5)
        self.login_label.bind('<Enter>', lambda label: self.link_on(self.login_label))
        self.login_label.bind('<Leave>', lambda label: self.link_off(self.login_label))
        
        self.logout_label = tk.Label(links, text='Logout', fg='blue', bg='white', cursor='hand2')
        self.logout_label['font'] = (None, 12, 'normal')
        self.logout_label.grid(column=1, row=0, padx=5, pady=5)
        self.logout_label.bind('<Enter>', lambda label: self.link_on(self.logout_label))
        self.logout_label.bind('<Leave>', lambda label: self.link_off(self.logout_label))

        self.register_label = tk.Label(links, text='Register', fg='blue', bg='white', cursor='hand2')
        self.register_label['font'] = (None, 12, 'normal')
        self.register_label.grid(column=2, row=0, padx=5, pady=5)
        self.register_label.bind('<Enter>', lambda label: self.link_on(self.register_label))
        self.register_label.bind('<Leave>', lambda label: self.link_off(self.register_label))

        self.exit_label = tk.Label(linksframe, text='Exit', fg='orangered', bg='white', cursor='hand2')
        self.exit_label['font'] = (None, 12, 'normal')
        self.exit_label.grid(column=2, row=0, padx=(5,10), pady=5, sticky='e')
        self.exit_label.bind('<Enter>', self.exit_enter)
        self.exit_label.bind('<Leave>', self.exit_leave)       

        # The user/admin frame is hidden until logged in
        adminlabel = tk.Label(self.adminframe, text='Admin stuff here', bg='white')
        adminlabel['font'] = (None, 12, 'normal')
        adminlabel.grid(column=0, row=0, padx=5, pady=5, sticky='new')

        self.footer = tk.Label(footerframe, text='my-python.org')
        self.footer['bg'] = '#333333'
        self.footer['fg'] = '#cecece'
        self.footer['font'] = ('cursive', 14, 'normal')
        self.footer['cursor'] = 'hand2'
        self.footer.grid(column=0, row=2, ipady=5)
        self.footer.bind('<Enter>', lambda event: self.footer_on(self.footer))
        self.footer.bind('<Leave>', lambda event: self.footer_off(self.footer))

    # These methods provide the hover effects
    def link_on(self, label):
        label['fg'] = 'orangered'

    def link_off(self, label):
        label['fg'] = 'blue'

    def exit_enter(self, event):
        self.exit_label['fg'] = 'red'

    def exit_leave(self, event):
        self.exit_label['fg'] = 'tomato'

    def footer_on(self, label):
        label['fg'] = '#ffffff'

    def footer_off(self, label):
        label['fg'] = '#cecece'


class LoginForm:
    def __init__(self, parent):
        self.parent = parent
        self.window = tk.Toplevel(None)
        self.window.title('Login Form')
        self.window.minsize(800,200)
        self.window.columnconfigure(0, weight=1)
        self.window.rowconfigure(0, weight=1)

        container = tk.Frame(self.window, bg='#555555')
        container.grid(column=0, row=0, sticky='new', padx=5, pady=5)
        container.grid_columnconfigure(0, weight=3)

        formframe = tk.Frame(container, bg='#555555')
        formframe.grid(column=0, row=1, sticky='new', pady=10)

        btnframe = tk.Frame(container, bg='#555555')
        btnframe.grid(column=0, row=2, sticky='new', pady=5)

        # Simple header label
        header = tk.Label(container, text='Main Page')
        header['font'] = ('cursive', 30, 'bold')
        header['bg'] = '#333333'
        header['fg'] = 'whitesmoke'
        header['relief'] = 'solid'
        header['borderwidth'] = 1
        header.grid(column=0, row=0, sticky='new', ipady=10)

        # Create the form headers and fields
        label = tk.Label(formframe, text='Email:', bg='#555555', fg='white', anchor='w')
        label['font'] = (None, 12, 'bold')
        label.grid(column=0, row=0, sticky='new', pady=4, padx=2)

        label = tk.Label(formframe, text='Password:', bg='#555555', fg='white', anchor='w')
        label['font'] = (None, 12, 'bold')
        label.grid(column=0, row=1, sticky='new', pady=4, padx=2) 

        self.user = tk.Entry(formframe, font=(None, 12, 'normal'))
        self.user.focus()
        self.user.grid(column=1, row=0, sticky='new', pady=4, padx=2)

        self.passwd = tk.Entry(formframe, font=(None, 12, 'normal'))
        self.passwd.grid(column=1, row=1, sticky='new', pady=4, padx=2)

        # Create the buttons
        self.loginbtn = tk.Button(btnframe, text='Login', bg='#BCD4E6', fg='black')
        self.loginbtn['activebackground'] = '#6CA0DC'
        self.loginbtn['activeforeground'] = 'white'
        self.loginbtn['font'] = (None, 12, 'normal')
        self.loginbtn['cursor'] = 'hand2'
        self.loginbtn['highlightbackground'] = 'black'
        self.loginbtn['highlightcolor'] = 'black'
        self.loginbtn.grid(column=0, row=0, sticky='new', padx=5, pady=5)

        self.cancelbtn = tk.Button(btnframe, text='Cancel', bg='tomato', fg='black')
        self.cancelbtn['font'] = (None, 12, 'normal')
        self.cancelbtn['activebackground'] = 'orangered'
        self.cancelbtn['activeforeground'] = 'white'
        self.cancelbtn['cursor'] = 'hand2'
        self.cancelbtn['highlightbackground'] = 'black'
        self.cancelbtn['highlightcolor'] = 'black'
        self.cancelbtn.grid(column=1, row=0, sticky='new', padx=5, pady=5)

        self.msg = tk.Label(container, bg='#555555', fg='white', font=(None, 12, 'bold'))
        self.msg.grid(column=0, row=3, sticky='new')
                

class RegisterForm:
    def __init__(self, parent):
        self.parent = parent
        self.window = tk.Toplevel(None)
        self.window.title('Registration Form')
        self.window.minsize(800,250)
        self.window.columnconfigure(0, weight=1)
        self.window.rowconfigure(0, weight=1)

        container = tk.Frame(self.window, bg='#555555')
        container.grid(column=0, row=0, sticky='new', padx=5, pady=5)
        container.grid_columnconfigure(0, weight=3)

        formframe = tk.Frame(container, bg='#555555')
        formframe.grid(column=0, row=1, sticky='new', pady=10)
        

        btnframe = tk.Frame(container, bg='#555555')
        btnframe.grid(column=0, row=2, sticky='new', pady=5)

        # Simple header label
        header = tk.Label(container, text='Registration Page')
        header['font'] = ('cursive', 30, 'bold')
        header['bg'] = '#333333'
        header['fg'] = 'whitesmoke'
        header['relief'] = 'solid'
        header['borderwidth'] = 1
        header.grid(column=0, row=0, sticky='new', ipady=10)

        # Create Field Headers
        label = tk.Label(formframe, text='Name:', bg='#555555', fg='white', anchor='w', pady=5, font=(None, 12, 'bold'))
        label.grid(column=0, row=0, sticky='new', pady=5)
        label = tk.Label(formframe, text='Email:', bg='#555555', fg='white', anchor='w', pady=5, font=(None, 12, 'bold'))
        label.grid(column=0, row=1, sticky='new', pady=5)
        label = tk.Label(formframe, text='Password:', bg='#555555', fg='white', anchor='w', pady=5, font=(None, 12, 'bold'))
        label.grid(column=0, row=2, sticky='new', pady=5)

        #Create Fields
        self.name = tk.Entry(formframe, font=(None, 12, 'normal'))
        self.name.grid(column=1, row=0, sticky='new', pady=5, padx=5)
        self.email = tk.Entry(formframe, font=(None, 12, 'normal'))
        self.email.grid(column=1, row=1, sticky='new', pady=5, padx=5)
        self.password = tk.Entry(formframe, font=(None, 12, 'normal'))
        self.password.grid(column=1, row=2, sticky='new', pady=5, padx=5)

        # Create the buttons
        self.registerbtn = tk.Button(btnframe, text='Register', bg='#BCD4E6', fg='black')
        self.registerbtn['activebackground'] = '#6CA0DC'
        self.registerbtn['activeforeground'] = 'white'
        self.registerbtn['font'] = (None, 12, 'normal')
        self.registerbtn['cursor'] = 'hand2'
        self.registerbtn['highlightbackground'] = 'black'
        self.registerbtn['highlightcolor'] = 'black'
        self.registerbtn.grid(column=0, row=0, sticky='new', padx=5, pady=5)

        self.cancelbtn = tk.Button(btnframe, text='Cancel', bg='tomato', fg='black')
        self.cancelbtn['font'] = (None, 12, 'normal')
        self.cancelbtn['activebackground'] = 'orangered'
        self.cancelbtn['activeforeground'] = 'white'
        self.cancelbtn['cursor'] = 'hand2'
        self.cancelbtn['highlightbackground'] = 'black'
        self.cancelbtn['highlightcolor'] = 'black'
        self.cancelbtn.grid(column=1, row=0, sticky='new', padx=5, pady=5)

        self.msg = tk.Label(container, font=(None, 14, 'bold'), fg='white')
        self.msg.grid(column=0, row=3, sticky='new')


class Controller:
    '''
    Controll class handles all communication between the classes
    '''
    def __init__(self, database, window, loginform, registerform):
        # Set some class variables
        self.database = database
        self.window = window
        self.loginform = loginform
        self.registerform = registerform
        self.id = None

        # This hides the user/admin frame upon script start
        self.window.adminframe.grid_remove()

        # Withdraw login and register forms
        self.loginform.window.withdraw()
        self.registerform.window.withdraw()

        # Window Link Commands
        self.window.login_label.bind('<Button-1>', self.loginpage)
        self.window.logout_label.bind('<Button-1>', self.logout)
        self.window.register_label.bind('<Button-1>', self.registerpage)
        self.window.exit_label.bind('<Button-1>', self.terminate)
        self.loginform.window.protocol('WM_DELETE_WINDOW', lambda: self.close(self.loginform.window))
        self.registerform.window.protocol('WM_DELETE_WINDOW', lambda: self.close(self.registerform.window))
        self.window.footer.bind('<Button-1>', self.link)

        # Button Commands
        self.loginform.cancelbtn['command'] = lambda: self.close(self.loginform.window)
        self.loginform.loginbtn['command'] = self.login
        self.registerform.registerbtn['command'] = self.register
        self.registerform.cancelbtn['command'] = lambda: self.close(self.registerform.window)

    def link(self, event):
        webbrowser.open('http://my-python.org')

    def loginpage(self, event):
        ''' Pulls up the login form and withdraws the main window '''
        self.loginform.msg['text'] = ''
        self.loginform.user.delete(0, 'end')
        self.loginform.passwd.delete(0, 'end')
        self.window.parent.withdraw()
        self.loginform.window.deiconify()

    def login(self):
        '''
        Method for getting the email and password from the loginform class form.
        Checks if the fields are empty, and if the user and email are in the database.
        Displays the appropiate message if error. If all is good, withdraws the login form,
        clears the fields and returns to the main window showing the user/admin content.
        '''
        user, password = self.loginform.user.get(), self.loginform.passwd.get()
        self.update()

        if user.lower().strip() == '' or password.strip() == '':
            self.loginform.msg['text'] = 'Either email or password is empty.'
            self.loginform.msg['bg'] = '#333333'

        elif not self.database.login(user, password):
            self.loginform.user.focus()
            self.loginform.msg['text'] = 'Either email or password is incorrect. Please try again.'
            self.loginform.msg['bg'] = '#333333'

        else:
            self.window.adminframe.grid()
            self.update()
            self.close(self.loginform.window)

    def update(self):
        ''' Method resets all the form msg text and clears fields. '''
        self.loginform.msg['text'] = ''
        self.loginform.msg['bg'] = '#555555'
        self.loginform.user.delete(0, 'end')
        self.loginform.passwd.delete(0, 'end')

        self.registerform.msg['text'] = ''
        self.registerform.msg['bg'] = '#555555'
        self.registerform.name.delete(0, 'end')
        self.registerform.email.delete(0, 'end')
        self.registerform.password.delete(0, 'end')

    def logout(self, event):
        ''' Logs out the user and hides the user/admin frame '''
        self.window.adminframe.grid_remove()
        
    def registerpage(self, event):
        ''' Method withdraws main window and pulls up regustration form '''
        self.window.parent.withdraw()
        self.registerform.window.deiconify()
        self.registerform.msg['bg'] = '#555555'
        self.registerform.msg['text'] = ''

    def register(self):
        ''' Method gets values from the register form and checks if all fields are entered
            and does a simple check of email format
        '''
        name, email, password = self.registerform.name.get(), self.registerform.email.get(), self.registerform.password.get()
        if name == '' or email == '' or password == '':
            self.registerform.msg['text'] = 'All fields are required'
            self.registerform.msg['bg'] = '#333333'
        else:
            try:
                self.database.register(name, email, password)
            except sq.IntegrityError as error:
                if 'constraint' in str(error) and 'customer.email' in str(error):
                    self.registerform.msg['text'] = 'That email already exist in the database.'
                    self.registerform.msg['bg'] = '#333333'
                    self.registerform.email.delete(0, 'end')
                elif 'CHECK' in str(error):
                    self.registerform.msg['text'] = 'That is not a valid email.'
                    self.registerform.msg['bg'] = '#333333'
                    self.registerform.email.delete(0, 'end')
                else:
                    self.registerform.msg['text'] = 'An unkwon error has occurred'
                    self.registerform.msg['bg'] = '#333333'
            else:
                self.registerform.name.delete(0, 'end')
                self.registerform.email.delete(0, 'end')
                self.registerform.password.delete(0, 'end')
                self.registerform.window.withdraw()
                self.loginform.window.deiconify()
        
    def terminate(self,event):
        ''' Method destroys root window and ends script. '''
        self.window.parent.destroy()

    def close(self, window):
        ''' Method is used to withdraw various toplevel windows and returns the main window. '''
        window.withdraw()
        self.update()
        self.window.parent.deiconify()

if __name__ == '__main__':
    root = tk.Tk()
    root['pady'] = 5
    root['padx'] = 5
    controller = Controller(Database(), Window(root), LoginForm(root), RegisterForm(root))
    controller.database.create()
    root.mainloop()
likes this post
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Current Project menator01 3 2,360 Apr-27-2022, 03:35 PM
Last Post: menator01
  Created a simple GUI to get myself started with TkInter! bixitz 4 3,101 Apr-04-2019, 05:33 PM
Last Post: buran

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020