Python Forum
[Tkinter] data enterred through gui is not storing in sqlite3 database
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] data enterred through gui is not storing in sqlite3 database
#11
I have no idea what you are doing. You haven't posted any code for a while.
Reply
#12
Although there are better ways, you might could do something like this with your database.

#! /usr/bin/env python3

import sqlite3
from datetime import datetime
from functools import partial

class Database:
    DBFILE = 'question_bank'
    def __init__(self):
        conn = sqlite3.connect(Database.DBFILE)
        cursor = conn.cursor()
        cursor.execute(''' select count(name) from sqlite_master where type='table' \
        and name='question_bank' ''')

        if cursor.fetchone()[0] == 1:
            conn.close()
            pass
        else:
            cursor.execute('''create table if not exists questions
            (id integer primary key autoincrement,
            module_id integer not null,
            question varchar(255) not null)''')
            conn.commit()

            cursor.execute('''create table if not exists modules
            (id integer primary key autoincrement,
            name varchar(100) not null,
            date_created timestamp)''')
            conn.commit()
            conn.close()

    def add(self, table=None, id=None, arg=None):
        conn = sqlite3.connect(Database.DBFILE)
        if table == 'modules':
            conn.execute('insert into modules (name, date_created) values (?, ?)', (arg, datetime.now()))
            conn.commit()
            conn.close()
        else:
            conn.execute('insert into questions (module_id, question) values (?, ?)', (id, arg))
            conn.commit()
            conn.close()

    def view(self, table):
        conn = sqlite3.connect(Database.DBFILE)
        cursor = conn.cursor()
        cursor.execute(f'select * from {table}')
        rows = cursor.fetchall()
        for row in rows:
            if table == 'modules':
                print(f'ID: {row[0]} Module: {row[1]} Created: {row[2]}')
            else:
                print(f'ID: {row[0]} Module ID: {row[1]} Question: {row[2]}')


db = Database()
db.add(table='modules', id=None, arg='math')
db.add(table='questions', id=1, arg='What was the question?')
print('Module Table')
db.view('modules')
print()
print()
print('Question Table')
db.view('questions')
Output:
Module Table ID: 1 Module: math Created: 2021-12-03 13:15:03.687650 Question Table ID: 1 Module ID: 1 Question: What was the question?
Hilal 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
#13
(Dec-03-2021, 07:18 PM)menator01 Wrote: Although there are better ways, you might could do something like this with your database.

#! /usr/bin/env python3

import sqlite3
from datetime import datetime
from functools import partial

class Database:
    DBFILE = 'question_bank'
    def __init__(self):
        conn = sqlite3.connect(Database.DBFILE)
        cursor = conn.cursor()
        cursor.execute(''' select count(name) from sqlite_master where type='table' \
        and name='question_bank' ''')

        if cursor.fetchone()[0] == 1:
            conn.close()
            pass
        else:
            cursor.execute('''create table if not exists questions
            (id integer primary key autoincrement,
            module_id integer not null,
            question varchar(255) not null)''')
            conn.commit()

            cursor.execute('''create table if not exists modules
            (id integer primary key autoincrement,
            name varchar(100) not null,
            date_created timestamp)''')
            conn.commit()
            conn.close()

    def add(self, table=None, id=None, arg=None):
        conn = sqlite3.connect(Database.DBFILE)
        if table == 'modules':
            conn.execute('insert into modules (name, date_created) values (?, ?)', (arg, datetime.now()))
            conn.commit()
            conn.close()
        else:
            conn.execute('insert into questions (module_id, question) values (?, ?)', (id, arg))
            conn.commit()
            conn.close()

    def view(self, table):
        conn = sqlite3.connect(Database.DBFILE)
        cursor = conn.cursor()
        cursor.execute(f'select * from {table}')
        rows = cursor.fetchall()
        for row in rows:
            if table == 'modules':
                print(f'ID: {row[0]} Module: {row[1]} Created: {row[2]}')
            else:
                print(f'ID: {row[0]} Module ID: {row[1]} Question: {row[2]}')


db = Database()
db.add(table='modules', id=None, arg='math')
db.add(table='questions', id=1, arg='What was the question?')
print('Module Table')
db.view('modules')
print()
print()
print('Question Table')
db.view('questions')
Output:
Module Table ID: 1 Module: math Created: 2021-12-03 13:15:03.687650 Question Table ID: 1 Module ID: 1 Question: What was the question?

Thank you very much for adding classes to my code. I will play with this code now, also my code was working with MySQL database so I used it instead of sqlite. Thankyou everyone for your support. Heart
Reply
#14
(Dec-03-2021, 05:59 PM)deanhystad Wrote: I have no idea what you are doing. You haven't posted any code for a while.
Thankyou very much for your help deanhystad. My code is now working but I dropped sqlite from my code and used MySQL which was working fine with my code.
Reply
#15
I was intrigued by your project and started working with it.
Although all buttons and functions are not done, this is what I have as of now.
Only modules can be added and deleted.

#! /usr/bin/env python3

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import sqlite3
from datetime import datetime
from functools import partial
from os import sys

# Class for all database functions - add, delete, and edit records
class Database:
    # Define a class global
    DBFILE = 'question_bank'
    def __init__(self):
        '''
        Create and connect to the database file
        Get the cursor object
        Check the database for the tables
        If the tables do not exists, create them
        '''
        conn = sqlite3.connect(Database.DBFILE)
        cursor = conn.cursor()
        cursor.execute(''' select count(name) from sqlite_master where type='table' \
        and name='question_bank' ''')

        if cursor.fetchone()[0] == 1:
            conn.close()
            pass
        else:
            cursor.execute('''create table if not exists questions
            (id integer primary key autoincrement,
            module_id integer not null,
            question varchar(255) not null)''')
            conn.commit()

            cursor.execute('''create table if not exists modules
            (id integer primary key autoincrement,
            name varchar(100) not null unique,
            date_created timestamp)''')
            conn.commit()
            conn.close()

    # Method for adding entries to the tables
    def add(self, table=None, id=None, arg=None):
        # Get the connection
        conn = sqlite3.connect(Database.DBFILE)
        # Check which table we want to enter data
        if table == 'modules':
            try:
                conn.execute('insert into modules (name, date_created) values (?, ?)', (arg, datetime.now()))
                conn.commit()
                conn.close()
            except sqlite3.IntegrityError as error:
                messagebox.showwarning('Error', f'Error: {arg.title()} already exists in the database.')
                pass
        else:
            try:
                conn.execute('insert into questions (module_id, question) values (?, ?)', (id, arg))
                conn.commit()
                conn.close()
            except sqlite3.IntegrityError as error:
                return f'Error: That question already exists.'

    # Method for deleting records
    def delete(self, table, module):
        conn = sqlite3.connect(Database.DBFILE)
        if table == 'modules':
            conn.execute('delete from modules where name = ?', (module,))
            conn.commit()
            conn.close()
        else:
            print(f'Hi questions!')

    # Method for editing records
    def edit(self):
        pass

    # Method for getting data from tables to view
    def view(self, table):
        conn = sqlite3.connect(Database.DBFILE)
        cursor = conn.cursor()
        cursor.execute(f'select * from {table}')
        rows = cursor.fetchall()
        return rows

# Class for setting up the add module window
class AddWindow:
    def __init__(self, window, listbox, get_list, task):
        # Initiate the Database class, set some varibles from the main window
        # iconify the main window
        self.db = Database()
        self.window = window
        self.listbox = listbox
        self.get_list = get_list
        self.task = task
        window.iconify()

        # Create a toplevel window and form
        self.top = tk.Toplevel()
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)
        self.top['padx'] = 5
        self.top['pady'] = 5
        self.top.geometry('400x200+250+250')
        self.top.resizable(False, False)

        self.container = tk.LabelFrame(self.top)
        self.container['text'] = 'Add a new module to the database'
        self.container.grid(column=0, row=0, sticky='news')
        self.container.grid_columnconfigure(1, weight=3)

        label = tk.Label(self.container)
        label['text'] = 'Module Name: '
        label.grid(column=0, row=0, sticky='new', padx=5, pady=8)

        module = tk.StringVar()
        style = ttk.Style()
        style.configure('TEntry', padding='5 1 5 1')
        self.entry = ttk.Entry(self.container, style='TEntry')
        self.entry['textvariable'] = module
        self.entry.focus_force()
        self.entry.grid(column=1, row=0, sticky='new', padx=5, pady=8)

        self.button = tk.Button(self.container, text='Submit')
        self.button['command'] = partial(self.add_module, self.entry)
        self.button.grid(column=1, row=1, columnspan=2, sticky='e', padx=5)
        self.entry.bind('<Return>', partial(self.add_module, self.entry))

    # Method for adding modules to the database, deiconify the main window and
    # destroy the top window
    def add_module(self, module, event=None):
        module = module.get()
        if module:
            self.db.add(table='modules', arg=module.lower())
            self.entry.delete(0, tk.END)
            self.listbox.delete(0, tk.END)
            self.get_list(self.task)
            self.window.deiconify()
            self.top.destroy()

        else:
            messagebox.showwarning('No Module Entered', 'Please type in a module name to add')

class Window:
    def __init__(self, parent):
        self.parent = parent
        self.parent.columnconfigure(0, weight=1)
        self.parent.rowconfigure(0, weight=1)

        # Initiate the Database class
        self.db = Database()

        # Create a container for widgets
        self.container = tk.Frame(self.parent, padx=8, pady=4)
        self.container['borderwidth'] = 1
        self.container['highlightcolor'] = 'black'
        self.container['highlightbackground'] = 'black'
        self.container['highlightthickness'] = 1
        self.container.grid(column=0, row=0, sticky='new', pady=8, padx=8)
        self.container.grid_columnconfigure(0, weight=3)

        # Create the header
        header = tk.Label(self.container, text='Administration Tools')
        header['font'] = ('verdana', 16, 'bold')
        header['bg'] = 'lightgray'
        header.grid(column=0, row=0, sticky='new')

        # What operations do we want
        self.option = tk.LabelFrame(self.container, text='Choose a task')
        self.option.grid(column=0, row=1, sticky='new')
        self.option.grid_columnconfigure(0, weight=3, uniform='options')
        self.option.grid_columnconfigure(1, weight=3, uniform='options')

        task = tk.StringVar()
        task.set('option1')

        self.option1 = tk.Radiobutton(self.option, text='Modules')
        self.option1['variable'] = task
        self.option1['value'] = 'option1'
        self.option1['command'] = partial(self.get_list, task)
        self.option1.grid(column=0, row=0, sticky='new')

        self.option2 = tk.Radiobutton(self.option, text='Questions')
        self.option2['variable'] = task
        self.option2['value'] = 'option2'
        self.option2['command'] = partial(self.get_list, task)
        self.option2.grid(column=1, row=0, sticky='new')

        # Create a listbox
        frame = tk.Frame(self.container, bg='white')
        frame['borderwidth'] = 1
        frame['highlightcolor'] = 'black'
        frame['highlightbackground'] = 'black'
        frame['highlightthickness'] = 1
        frame.grid(column=0, row=2, sticky='new', ipadx=5, ipady=5, pady=8)
        frame.grid_columnconfigure(0, weight=3)

        self.listbox = tk.Listbox(frame)
        self.listbox['borderwidth'] = 0
        self.listbox['highlightbackground'] = 'white'
        self.listbox['highlightcolor'] = 'white'
        self.listbox['selectmode'] = tk.SINGLE
        self.listbox.grid(column=0, row=0, sticky='news', padx=5, pady=5)

        # Populate the listbox on opening the window
        self.get_list(task)

    def delete(self, table, task):
        if table == 'modules':
            index = self.listbox.curselection()[0]
            confirm = messagebox.askokcancel('Delete Module', f'You are about to delete this module ( {self.listbox.get(index)} ).')
            if confirm:
                self.db.delete('modules', self.listbox.get(index).lower())
            else:
                pass
        else:
            pass
        self.get_list(task)

    # Method for changing button color on entring
    def enter(self, btn, event):
        if btn['text'].lower() == 'exit':
            btn['bg'] = 'red'
        else:
            btn['bg'] = 'lightblue'

    # Method for restoring button colors when exiting
    def leave(self, btn, event):
        if btn['text'].lower() == 'exit':
            btn['bg'] = 'tomato'
        else:
            btn['bg'] = 'lightgray'

    # Method for populating the listboxes
    # If option1 we want the modules else the questions
    def get_list(self, task):
        self.listbox.delete(0, tk.END)

        if task.get() == 'option1':
            for item in self.db.view('modules'):
                self.listbox.insert(item[0], item[1].title())
            self.listbox.select_set(0)

            buttons = {
            'Add':partial(AddWindow, self.parent, self.listbox, self.get_list, task),
            'Delete':partial(self.delete, 'modules', task), 'Edit':None, 'Exit':sys.exit
            }
        else:
            for item in self.db.view('questions'):
                self.listbox.insert(tk.END, item)

            buttons = {
            'Add':partial(print, 'hello'),
            'Delete':None, 'Edit':None, 'Exit':sys.exit
            }

        # Create a container for the buttons
        btn_frame = tk.Frame(self.container)
        btn_frame.grid(column=0, row=3, sticky='new', pady=10)
        for btn in range(4):
            btn_frame.columnconfigure(btn, weight=3, uniform='buttons')

        # Control buttons and commands
        i = 0
        color = 'lightgray'
        for btn, command in buttons.items():
            if btn == 'Exit':
                color = 'tomato'
            self.button = tk.Button(btn_frame, bg=color)
            self.button['cursor'] = 'hand2'
            self.button['text'] = btn
            self.button['command'] = command
            self.button.grid(column=i, row=0, sticky='new', padx=1)
            i += 1

            self.button.bind('<Enter>', partial(self.enter, self.button))
            self.button.bind('<Leave>', partial(self.leave, self.button))




def main():
    root = tk.Tk()
    root.title('Administration Tools')
    root.geometry('800x350+250+250')
    root['padx'] = 3
    root['pady'] = 5
    root.resizable(False, False)
    Window(root)
    root.mainloop()

main()
Hilal 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
#16
(Dec-05-2021, 07:59 PM)menator01 Wrote: I was intrigued by your project and started working with it.
Although all buttons and functions are not done, this is what I have as of now.
Only modules can be added and deleted.

#! /usr/bin/env python3

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import sqlite3
from datetime import datetime
from functools import partial
from os import sys

class Database:
    DBFILE = 'question_bank'
    def __init__(self):
        conn = sqlite3.connect(Database.DBFILE)
        cursor = conn.cursor()
        cursor.execute(''' select count(name) from sqlite_master where type='table' \
        and name='question_bank' ''')

        if cursor.fetchone()[0] == 1:
            conn.close()
            pass
        else:
            cursor.execute('''create table if not exists questions
            (id integer primary key autoincrement,
            module_id integer not null,
            question varchar(255) not null)''')
            conn.commit()

            cursor.execute('''create table if not exists modules
            (id integer primary key autoincrement,
            name varchar(100) not null unique,
            date_created timestamp)''')
            conn.commit()
            conn.close()

    def add(self, table=None, id=None, arg=None):
        conn = sqlite3.connect(Database.DBFILE)
        if table == 'modules':
            try:
                conn.execute('insert into modules (name, date_created) values (?, ?)', (arg, datetime.now()))
                conn.commit()
                conn.close()
            except sqlite3.IntegrityError as error:
                messagebox.showwarning('Error', f'Error: {arg.title()} already exists in the database.')
                pass
        else:
            try:
                conn.execute('insert into questions (module_id, question) values (?, ?)', (id, arg))
                conn.commit()
                conn.close()
            except sqlite3.IntegrityError as error:
                return f'Error: That question already exists.'

    def delete(self, table, module):
        conn = sqlite3.connect(Database.DBFILE)
        if table == 'modules':
            conn.execute('delete from modules where name = ?', (module,))
            conn.commit()
            conn.close()
        else:
            print(f'Hi questions!')

    def view(self, table):
        conn = sqlite3.connect(Database.DBFILE)
        cursor = conn.cursor()
        cursor.execute(f'select * from {table}')
        rows = cursor.fetchall()
        if table == 'modules':
            return rows
        else:
            return rows

# Class for setting up the add module window
class AddWindow:
    def __init__(self, window, listbox, get_list, task):
        # Initiate the Database class, set some varibles from the main window
        # iconify the main window
        self.db = Database()
        self.window = window
        self.listbox = listbox
        self.get_list = get_list
        self.task = task
        window.iconify()

        # Create a toplevel window and form
        self.top = tk.Toplevel()
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)
        self.top['padx'] = 5
        self.top['pady'] = 5
        self.top.geometry('400x200+250+250')
        self.top.resizable(False, False)

        self.container = tk.LabelFrame(self.top)
        self.container['text'] = 'Add a new module to the database'
        self.container.grid(column=0, row=0, sticky='news')
        self.container.grid_columnconfigure(1, weight=3)

        label = tk.Label(self.container)
        label['text'] = 'Module Name: '
        label.grid(column=0, row=0, sticky='new', padx=5, pady=8)

        module = tk.StringVar()
        style = ttk.Style()
        style.configure('TEntry', padding='5 1 5 1')
        self.entry = ttk.Entry(self.container, style='TEntry')
        self.entry['textvariable'] = module
        self.entry.focus_force()
        self.entry.grid(column=1, row=0, sticky='new', padx=5, pady=8)

        self.button = tk.Button(self.container, text='Submit')
        self.button['command'] = partial(self.add_module, self.entry)
        self.button.grid(column=1, row=1, columnspan=2, sticky='e', padx=5)
        self.entry.bind('<Return>', partial(self.add_module, self.entry))

    # Method for adding modules to the database, deiconify the main window and
    # destroy the top window
    def add_module(self, module, event=None):
        module = module.get()
        if module:
            self.db.add(table='modules', arg=module.lower())
            self.entry.delete(0, tk.END)
            self.listbox.delete(0, tk.END)
            self.get_list(self.task)
            self.window.deiconify()
            self.top.destroy()

        else:
            messagebox.showwarning('No Module Entered', 'Please type in a module name to add')

class Window:
    def __init__(self, parent):
        self.parent = parent
        self.parent.columnconfigure(0, weight=1)
        self.parent.rowconfigure(0, weight=1)

        # Initiate the Database class
        self.db = Database()

        # Create a container for widgets
        self.container = tk.Frame(self.parent, padx=8, pady=4)
        self.container['borderwidth'] = 1
        self.container['highlightcolor'] = 'black'
        self.container['highlightbackground'] = 'black'
        self.container['highlightthickness'] = 1
        self.container.grid(column=0, row=0, sticky='new', pady=8, padx=8)
        self.container.grid_columnconfigure(0, weight=3)

        # Create the header
        header = tk.Label(self.container, text='Administration Tools')
        header['font'] = ('verdana', 16, 'bold')
        header['bg'] = 'lightgray'
        header.grid(column=0, row=0, sticky='new')

        # What operations do we want
        self.option = tk.LabelFrame(self.container, text='Choose a task')
        self.option.grid(column=0, row=1, sticky='new')
        self.option.grid_columnconfigure(0, weight=3, uniform='options')
        self.option.grid_columnconfigure(1, weight=3, uniform='options')

        task = tk.StringVar()
        task.set('option1')

        self.option1 = tk.Radiobutton(self.option, text='Modules')
        self.option1['variable'] = task
        self.option1['value'] = 'option1'
        self.option1['command'] = partial(self.get_list, task)
        self.option1.grid(column=0, row=0, sticky='new')

        self.option2 = tk.Radiobutton(self.option, text='Questions')
        self.option2['variable'] = task
        self.option2['value'] = 'option2'
        self.option2['command'] = partial(self.get_list, task)
        self.option2.grid(column=1, row=0, sticky='new')

        # Create a listbox
        frame = tk.Frame(self.container, bg='white')
        frame['borderwidth'] = 1
        frame['highlightcolor'] = 'black'
        frame['highlightbackground'] = 'black'
        frame['highlightthickness'] = 1
        frame.grid(column=0, row=2, sticky='new', ipadx=5, ipady=5, pady=8)
        frame.grid_columnconfigure(0, weight=3)

        self.listbox = tk.Listbox(frame)
        self.listbox['borderwidth'] = 0
        self.listbox['highlightbackground'] = 'white'
        self.listbox['highlightcolor'] = 'white'
        self.listbox['selectmode'] = tk.SINGLE
        self.listbox.grid(column=0, row=0, sticky='news', padx=5, pady=5)

        # Populate the listbox on opening the window
        self.get_list(task)

    def delete(self, table, task):
        if table == 'modules':
            index = self.listbox.curselection()[0]
            confirm = messagebox.askokcancel('Delete Module', f'You are about to delete this module ( {self.listbox.get(index)} ).')
            if confirm:
                self.db.delete('modules', self.listbox.get(index).lower())
            else:
                pass
        else:
            pass
        self.get_list(task)

    # Method for changing button color on entring
    def enter(self, btn, event):
        if btn['text'].lower() == 'exit':
            btn['bg'] = 'red'
        else:
            btn['bg'] = 'lightblue'

    # Method for restoring button colors when exiting
    def leave(self, btn, event):
        if btn['text'].lower() == 'exit':
            btn['bg'] = 'tomato'
        else:
            btn['bg'] = 'lightgray'

    # Method for populating the listboxes
    def get_list(self, task):
        self.listbox.delete(0, tk.END)

        if task.get() == 'option1':
            for item in self.db.view('modules'):
                self.listbox.insert(item[0], item[1].title())
            self.listbox.select_set(0)


            buttons = {
            'Add':partial(AddWindow, self.parent, self.listbox, self.get_list, task),
            'Delete':partial(self.delete, 'modules', task), 'Edit':None, 'Exit':sys.exit
            }
        else:
            buttons = {
            'Add':partial(print, 'hello'),
            'Delete':None, 'Edit':None, 'Exit':sys.exit
            }
            for item in self.db.view('questions'):
                self.listbox.insert(tk.END, item)

        # Create a container for the buttons
        btn_frame = tk.Frame(self.container)
        btn_frame.grid(column=0, row=3, sticky='new', pady=10)
        for btn in range(4):
            btn_frame.columnconfigure(btn, weight=3, uniform='buttons')

        # Control buttons and commands
        i = 0
        color = 'lightgray'
        for btn, command in buttons.items():
            if btn == 'Exit':
                color = 'tomato'
            self.button = tk.Button(btn_frame, bg=color)
            self.button['cursor'] = 'hand2'
            self.button['text'] = btn
            self.button['command'] = command
            self.button.grid(column=i, row=0, sticky='new', padx=1)
            i += 1

            self.button.bind('<Enter>', partial(self.enter, self.button))
            self.button.bind('<Leave>', partial(self.leave, self.button))




def main():
    root = tk.Tk()
    root.title('Administration Tools')
    root.geometry('800x350+250+250')
    root['padx'] = 3
    root['pady'] = 5
    root.resizable(False, False)
    Window(root)
    root.mainloop()

main()

This is exactly what I wanted to do, Thanks a lot for your time and help. You made it more beautiful and flexibleHeart Heart
Reply
#17
sorry posted the same comments twice.
Reply
#18
Have everything working except for the edit buttons. May finish later. For now I think I will try to do a pyqt5 version and clean the code up.
I have some repetitive code that should be eliminated.



#! /usr/bin/env python3

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import sqlite3
from datetime import datetime
from functools import partial
from os import sys

# Class for all database functions - add, delete, and edit records
class Database:
    # Define a class global
    DBFILE = 'question_bank'
    def __init__(self):
        '''
        Create and connect to the database file
        Get the cursor object
        Check the database for the tables
        If the tables do not exists, create them
        '''
        conn = sqlite3.connect(Database.DBFILE)
        cursor = conn.cursor()
        cursor.execute(''' select count(name) from sqlite_master where type='table' \
        and name='question_bank' ''')

        if cursor.fetchone()[0] == 1:
            conn.close()
            pass
        else:
            cursor.execute('''create table if not exists questions
            (id integer primary key autoincrement,
            module_id integer not null,
            question varchar(255) not null)''')
            conn.commit()

            cursor.execute('''create table if not exists modules
            (id integer primary key autoincrement,
            name varchar(100) not null unique,
            date_created timestamp)''')
            conn.commit()
            conn.close()

    # Method for adding entries to the tables
    def add(self, table=None, id=None, arg=None):
        # Get the connection
        conn = sqlite3.connect(Database.DBFILE)
        # Check which table we want to enter data
        if table == 'modules':
            try:
                conn.execute('insert into modules (name, date_created) values (?, ?)', (arg, datetime.now()))
                conn.commit()
                conn.close()
            except sqlite3.IntegrityError as error:
                messagebox.showwarning('Error', f'Error: {arg.title()} already exists in the database.')
                pass
        else:
            try:
                conn.execute('insert into questions (module_id, question) values (?, ?)', (id, arg))
                conn.commit()
                conn.close()
            except sqlite3.IntegrityError as error:
                return f'Error: That question already exists.'

    # Method for deleting records
    def delete(self, table=None, module=None, question=None):
        conn = sqlite3.connect(Database.DBFILE)
        if table == 'modules':
            cursor = conn.cursor()
            cursor.execute('select id from modules where name = ?', (module,))
            module_id = cursor.fetchone()[0]
            conn.execute('delete from questions where module_id = ?', (module_id,))
            conn.execute('delete from modules where name = ?', (module,))
            conn.commit()
            conn.close()
        else:
            conn.execute('delete from questions where question = ?', (question,))
            conn.commit()
            conn.close()

    # Method for editing records
    def edit(self):
        messagebox.showinfo('Not Done', 'This method has not been programmed yet.')
        pass

    def get_id(self, module):
        conn = sqlite3.connect(Database.DBFILE)
        cursor = conn.cursor()
        cursor.execute('select id from modules where name = ?', (module,))
        return cursor.fetchone()

    # Method for getting data from tables to view
    def view(self, table, *args, **kwargs):
        conn = sqlite3.connect(Database.DBFILE)
        cursor = conn.cursor()
        if table == 'modules':
            cursor.execute(f'select * from {table}')
        else:
            try:
                id = kwargs['id']
                cursor.execute(f'select * from {table} where module_id = ?', (id,))
            except ValueError as error:
                print(error)
        rows = cursor.fetchall()
        return rows

# Class for adding questions
class AddQuestion:
    def __init__(self, window, task, get_list):
        self.db = Database()
        self.window = window
        self.get_list = get_list
        self.task = task
        window.iconify()

        # Create toplevel window
        self.top = tk.Toplevel(None)
        self.top.title('Add, Edit, and Delete Questions')
        self.top.geometry('600x350+250+250')
        self.top.resizable(False, False)
        self.top['padx'] = 8
        self.top['pady'] = 5
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)


        container = tk.Frame(self.top)
        container['borderwidth'] = 1
        container['highlightthickness'] = 1
        container['highlightcolor'] = 'black'
        container['highlightbackground'] = 'black'
        container.grid(column=0, row=0, sticky='news')
        container.grid_columnconfigure(0, weight=0)
        container.grid_columnconfigure(1, weight=3)

        label = tk.Label(container, anchor='w', padx=3)
        label['font'] = ('sans', 10, 'bold underline')
        label['text'] = 'Choose Module'
        label.grid(column=0, row=0, sticky='new', pady=8, padx=3)

        label = tk.Label(container, anchor='w', padx=3)
        label['font'] = ('sans', 10, 'bold underline')
        label['text'] = 'Type in your question'
        label.grid(column=1, row=0, sticky='new', pady=8, padx=3)

        values = []
        for item in self.db.view('modules'):
            values.append(item[1].title())

        string = tk.StringVar()

        self.combobox = ttk.Combobox(container)
        self.combobox['values'] = values
        self.combobox['state'] = 'readonly'
        self.combobox['cursor'] = 'hand2'
        self.combobox.grid(column=0, row=1, sticky='new', padx=3)
        self.combobox.bind('<<ComboboxSelected>>', partial(self.get_index, self.combobox))
        self.combobox.current(0)

        self.entry = ttk.Entry(container)
        self.entry['textvariable'] = string
        self.entry.grid(column=1, row=1, sticky='new', padx=3)

        label = tk.Label(container)
        label['text'] = 'Question List'
        label['font'] = ('sans', 12, 'bold')
        label.grid(column=0, row=2, columnspan=2, sticky='new', padx=3, pady=5)

        frame = tk.Frame(container)
        frame['bg'] = 'white'
        frame['borderwidth'] = 1
        frame['highlightcolor'] = 'black'
        frame['highlightbackground'] = 'black'
        frame['highlightthickness'] = 1
        frame.grid(column=0, row=3, columnspan=2, sticky='news', padx=3)
        frame.grid_columnconfigure(0, weight=3)

        self.listbox = tk.Listbox(frame)
        self.listbox['borderwidth'] = 0
        self.listbox['highlightcolor'] = 'white'
        self.listbox['highlightbackground'] = 'white'
        self.listbox['highlightthickness'] = 1
        self.listbox.grid(column=0, columnspan=2, row=2, sticky='news', padx=5, pady=5)


        label = tk.Label(container)
        label['text'] = 'Tip: Use mouse wheel to scroll list'
        label['bg'] = 'lightyellow'
        label['font'] = ('sans', 8, 'italic')
        label['relief'] = 'groove'
        label.grid(column=0, row=4, columnspan=2, sticky='new', padx=3, pady=5)

        btn_container = tk.Frame(container)
        btn_container.grid(column=0, row=5, columnspan=2, sticky='new', ipadx=3, pady=5)
        for i in range(4):
            btn_container.grid_columnconfigure(i, weight=3, uniform='buttons')

        buttons = {
        'Add': partial(self.add, string),
        'Edit': self.db.edit,
        'Delete': partial(self.delete),
        'Done': partial(self.done),
        }

        i = 0
        bgcolor = 'lightgray'
        fgcolor = 'black'
        for btn, command in buttons.items():
            if btn == 'Done':
                bgcolor = 'burlywood'
                fgcolor = 'brown'
            self.button = tk.Button(btn_container, text=btn, bg=bgcolor, fg=fgcolor)
            self.button['command'] = command
            self.button['cursor'] = 'hand2'
            self.button['font'] = ('sans', 10, 'normal')
            self.button.grid(column=i, row=0, sticky='new', padx=2)
            i += 1

            self.button.bind('<Enter>', partial(self.enter, self.button))
            self.button.bind('<Leave>', partial(self.leave, self.button))
        self.get_questions()

    def get_index(self, string, event):
        string = string.get().lower()
        id = self.db.get_id(string)
        id = id[0]
        self.get_questions(id=id)


    def delete(self):
        try:
            index = self.listbox.curselection()[0]
            question = self.listbox.get(index)
            self.db.delete(table='questions', question=question.lower())
            module = self.combobox.get()
            id = self.db.get_id(module.lower())
            self.get_questions(id=id[0])
        except:
            pass

    def get_questions(self, *args, id=1, **kwargs):
        self.listbox.delete(0, tk.END)
        for question in self.db.view('questions', id=id):
            self.listbox.insert(question[0], question[2])
        self.listbox.select_set(0)

    def enter(self, btn, event):
        if btn['text'].lower() == 'done':
            btn['bg'] = 'sandybrown'
            btn['fg'] = 'white'
            btn['font'] = ('sans', 10, 'bold')
        else:
            btn['bg'] = 'lightblue'
            btn['fg'] = 'mediumblue'
            btn['font'] = ('sans', 10, 'bold')

    def leave(self, btn, event):
        if btn['text'].lower() == 'done':
            btn['bg'] = 'burlywood'
            btn['fg'] = 'brown'
            btn['font'] = ('sans', 10, 'normal')
        else:
            btn['bg'] = 'lightgray'
            btn['fg'] = 'black'
            btn['font'] = ('sans', 10, 'normal')

    def add(self, string, *args, **kwargs):
        string = string.get().lower()
        module = self.combobox.get()
        id = self.db.get_id(module.lower())
        self.db.add(table=None, id=id[0], arg=string)
        self.entry.delete(0, tk.END)
        self.get_questions(id=id[0])

    def done(self):
        self.get_list(self.task)
        self.task.set('option1')
        self.window.deiconify()
        self.top.destroy()

# Class for setting up the add module window
class AddModule:
    def __init__(self, window, listbox, get_list, task):
        # Initiate the Database class, set some varibles from the main window
        # iconify the main window
        self.db = Database()
        self.window = window
        self.listbox = listbox
        self.get_list = get_list
        self.task = task
        window.iconify()

        # Create a toplevel window and form
        self.top = tk.Toplevel()
        self.top.title('Add a module')
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)
        self.top['padx'] = 5
        self.top['pady'] = 5
        self.top.geometry('400x100+250+250')
        self.top.resizable(False, False)

        self.container = tk.LabelFrame(self.top)
        self.container['text'] = 'Add a new module to the database'
        self.container.grid(column=0, row=0, sticky='news')
        self.container.grid_columnconfigure(1, weight=3)

        label = tk.Label(self.container)
        label['text'] = 'Module Name: '
        label.grid(column=0, row=0, sticky='new', padx=5, pady=8)

        module = tk.StringVar()
        style = ttk.Style()
        style.configure('TEntry', padding='5 1 5 1')
        self.entry = ttk.Entry(self.container, style='TEntry')
        self.entry['textvariable'] = module
        self.entry.focus_force()
        self.entry.grid(column=1, row=0, sticky='new', padx=5, pady=8)

        self.button = tk.Button(self.container, text='Submit')
        self.button['command'] = partial(self.add_module, self.entry)
        self.button['cursor'] = 'hand2'
        self.button['bg'] = 'lightgray'
        self.button.grid(column=1, row=1, columnspan=2, sticky='e', padx=5)
        self.entry.bind('<Return>', partial(self.add_module, self.entry))
        self.button.bind('<Enter>', self.enter)
        self.button.bind('<Leave>', self.leave)

    def enter(self, event):
        self.button['bg'] = 'lightblue'

    def leave(self, event):
        self.button['bg'] = 'lightgray'

    # Method for adding modules to the database, deiconify the main window and
    # destroy the top window
    def add_module(self, module, event=None):
        module = module.get()
        if module:
            self.db.add(table='modules', arg=module.lower())
            self.entry.delete(0, tk.END)
            self.listbox.delete(0, tk.END)
            self.get_list(self.task)
            self.window.deiconify()
            self.top.destroy()

        else:
            messagebox.showwarning('No Module Entered', 'Please type in a module name to add')

class Window:
    def __init__(self, parent):
        self.parent = parent
        self.parent.columnconfigure(0, weight=1)
        self.parent.rowconfigure(0, weight=1)

        # Initiate the Database class
        self.db = Database()

        self.task = tk.StringVar()
        self.task.set('option1')

        # Create a container for widgets
        self.container = tk.Frame(self.parent, padx=4, pady=2)
        self.container['borderwidth'] = 1
        self.container['highlightcolor'] = 'black'
        self.container['highlightbackground'] = 'black'
        self.container['highlightthickness'] = 1
        self.container.grid(column=0, row=0, sticky='new', pady=8, padx=8)
        self.container.grid_columnconfigure(0, weight=3)

        # Create the header
        header = tk.Label(self.container, text='Administration Tools')
        header['font'] = ('verdana', 16, 'bold')
        header['bg'] = 'lightgray'
        header.grid(column=0, row=0, sticky='new')

        # What operations do we want
        self.option = tk.LabelFrame(self.container, text='Choose a task')
        self.option.grid(column=0, row=1, sticky='new')
        self.option.grid_columnconfigure(0, weight=3, uniform='options')
        self.option.grid_columnconfigure(1, weight=3, uniform='options')

        self.option1 = tk.Radiobutton(self.option, text='Modules')
        self.option1['variable'] = self.task
        self.option1['value'] = 'option1'
        self.option1['command'] = partial(self.get_list, self.task)
        self.option1.grid(column=0, row=0, sticky='new')

        self.option2 = tk.Radiobutton(self.option, text='Questions')
        self.option2['variable'] = self.task
        self.option2['value'] = 'option2'
        self.option2['command'] = partial(self.add_window)
        self.option2.grid(column=1, row=0, sticky='new')

        # Create a listbox
        frame = tk.Frame(self.container, bg='white')
        frame['borderwidth'] = 1
        frame['highlightcolor'] = 'black'
        frame['highlightbackground'] = 'black'
        frame['highlightthickness'] = 1
        frame.grid(column=0, row=2, sticky='new', ipadx=5, ipady=5, pady=8)
        frame.grid_columnconfigure(0, weight=3)

        self.listbox = tk.Listbox(frame)
        self.listbox['borderwidth'] = 0
        self.listbox['highlightbackground'] = 'white'
        self.listbox['highlightcolor'] = 'white'
        self.listbox['selectmode'] = tk.SINGLE
        self.listbox.grid(column=0, row=0, sticky='news', padx=5, pady=5)

        # Populate the listbox on opening the window
        self.get_list(self.task)

    # Method to check if any modules exist. If so go to the questions window.
    # Otherwise stays on the modules window
    def add_window(self):
        if self.listbox.curselection():
            AddQuestion(self.parent, self.task, self.get_list)
        else:
            messagebox.showwarning('No Modules', 'You have to add at least one module to add questions.')
            self.task.set('option1')

    # Method for editing entries
    def edit(self, table, task):
        messagebox.showinfo('Edit', 'This method has not been programmed yet.')

    def delete(self, table, task):
        try:
            index = self.listbox.curselection()[0]
            confirm = messagebox.askokcancel('Delete Module', f'You are about to delete this module ( {self.listbox.get(index)} ).')
            if confirm:
                self.db.delete('modules', self.listbox.get(index).lower())
            else:
                pass
        except:
            pass

        # Updates the listbox
        self.get_list(task)

    # Method for changing button color on entring
    def enter(self, btn, event):
        if btn['text'].lower() == 'exit':
            btn['bg'] = 'red'
            btn['fg'] = 'white'
            btn['font'] = ('sans', 10, 'bold')
        else:
            btn['bg'] = 'lightblue'
            btn['fg'] = 'mediumblue'
            btn['font'] = ('sans', 10, 'bold')

    # Method for restoring button colors when exiting
    def leave(self, btn, event):
        if btn['text'].lower() == 'exit':
            btn['bg'] = 'tomato'
            btn['fg'] = 'black'
            btn['font'] = ('sans', 10, 'normal')
        else:
            btn['bg'] = 'lightgray'
            btn['fg'] = 'black'
            btn['font'] = ('sans', 10, 'normal')

    # Method for populating the listboxes
    # If option1 we want the modules else the questions
    def get_list(self, task):
        self.listbox.delete(0, tk.END)

        for item in self.db.view('modules'):
            self.listbox.insert(item[0], item[1].title())
        self.listbox.select_set(0)

        buttons = {
        'Add':partial(AddModule, self.parent, self.listbox, self.get_list, self.task),
        'Edit':partial(self.edit, 'modules', self.task),
        'Delete':partial(self.delete, 'modules', self.task),
        'Exit':sys.exit
        }

        # Create a container for the buttons
        btn_frame = tk.Frame(self.container)
        btn_frame.grid(column=0, row=3, sticky='new', pady=10)
        for btn in range(4):
            btn_frame.columnconfigure(btn, weight=3, uniform='buttons')

        # Control buttons and commands
        i = 0
        color = 'lightgray'
        for btn, command in buttons.items():
            if btn == 'Exit':
                color = 'tomato'
            self.button = tk.Button(btn_frame, bg=color)
            self.button['cursor'] = 'hand2'
            self.button['text'] = btn
            self.button['font'] = ('sans', 10, 'normal')
            self.button['command'] = command
            self.button.grid(column=i, row=0, sticky='new', padx=1)
            i += 1

            self.button.bind('<Enter>', partial(self.enter, self.button))
            self.button.bind('<Leave>', partial(self.leave, self.button))

def main():
    root = tk.Tk()
    root.title('Administration Tools')
    root.geometry('800x350+250+250')
    root['padx'] = 3
    root['pady'] = 5
    root.resizable(False, False)
    Window(root)
    root.mainloop()

main()
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#19
I saw your video on youtube, it looks very nice now and the code is also amazing, Thank you for putting your hard work in this code, I will take a lot of ideas from it whenever I am stucked at coding a database application or a GUI. Heart Heart

(Dec-07-2021, 10:45 AM)menator01 Wrote: Have everything working except for the edit buttons. May finish later. For now I think I will try to do a pyqt5 version and clean the code up.
I have some repetitive code that should be eliminated.



#! /usr/bin/env python3

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import sqlite3
from datetime import datetime
from functools import partial
from os import sys

# Class for all database functions - add, delete, and edit records
class Database:
    # Define a class global
    DBFILE = 'question_bank'
    def __init__(self):
        '''
        Create and connect to the database file
        Get the cursor object
        Check the database for the tables
        If the tables do not exists, create them
        '''
        conn = sqlite3.connect(Database.DBFILE)
        cursor = conn.cursor()
        cursor.execute(''' select count(name) from sqlite_master where type='table' \
        and name='question_bank' ''')

        if cursor.fetchone()[0] == 1:
            conn.close()
            pass
        else:
            cursor.execute('''create table if not exists questions
            (id integer primary key autoincrement,
            module_id integer not null,
            question varchar(255) not null)''')
            conn.commit()

            cursor.execute('''create table if not exists modules
            (id integer primary key autoincrement,
            name varchar(100) not null unique,
            date_created timestamp)''')
            conn.commit()
            conn.close()

    # Method for adding entries to the tables
    def add(self, table=None, id=None, arg=None):
        # Get the connection
        conn = sqlite3.connect(Database.DBFILE)
        # Check which table we want to enter data
        if table == 'modules':
            try:
                conn.execute('insert into modules (name, date_created) values (?, ?)', (arg, datetime.now()))
                conn.commit()
                conn.close()
            except sqlite3.IntegrityError as error:
                messagebox.showwarning('Error', f'Error: {arg.title()} already exists in the database.')
                pass
        else:
            try:
                conn.execute('insert into questions (module_id, question) values (?, ?)', (id, arg))
                conn.commit()
                conn.close()
            except sqlite3.IntegrityError as error:
                return f'Error: That question already exists.'

    # Method for deleting records
    def delete(self, table=None, module=None, question=None):
        conn = sqlite3.connect(Database.DBFILE)
        if table == 'modules':
            cursor = conn.cursor()
            cursor.execute('select id from modules where name = ?', (module,))
            module_id = cursor.fetchone()[0]
            conn.execute('delete from questions where module_id = ?', (module_id,))
            conn.execute('delete from modules where name = ?', (module,))
            conn.commit()
            conn.close()
        else:
            conn.execute('delete from questions where question = ?', (question,))
            conn.commit()
            conn.close()

    # Method for editing records
    def edit(self):
        messagebox.showinfo('Not Done', 'This method has not been programmed yet.')
        pass

    def get_id(self, module):
        conn = sqlite3.connect(Database.DBFILE)
        cursor = conn.cursor()
        cursor.execute('select id from modules where name = ?', (module,))
        return cursor.fetchone()

    # Method for getting data from tables to view
    def view(self, table, *args, **kwargs):
        conn = sqlite3.connect(Database.DBFILE)
        cursor = conn.cursor()
        if table == 'modules':
            cursor.execute(f'select * from {table}')
        else:
            try:
                id = kwargs['id']
                cursor.execute(f'select * from {table} where module_id = ?', (id,))
            except ValueError as error:
                print(error)
        rows = cursor.fetchall()
        return rows

# Class for adding questions
class AddQuestion:
    def __init__(self, window, task, get_list):
        self.db = Database()
        self.window = window
        self.get_list = get_list
        self.task = task
        window.iconify()

        # Create toplevel window
        self.top = tk.Toplevel(None)
        self.top.title('Add, Edit, and Delete Questions')
        self.top.geometry('600x350+250+250')
        self.top.resizable(False, False)
        self.top['padx'] = 8
        self.top['pady'] = 5
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)


        container = tk.Frame(self.top)
        container['borderwidth'] = 1
        container['highlightthickness'] = 1
        container['highlightcolor'] = 'black'
        container['highlightbackground'] = 'black'
        container.grid(column=0, row=0, sticky='news')
        container.grid_columnconfigure(0, weight=0)
        container.grid_columnconfigure(1, weight=3)

        label = tk.Label(container, anchor='w', padx=3)
        label['font'] = ('sans', 10, 'bold underline')
        label['text'] = 'Choose Module'
        label.grid(column=0, row=0, sticky='new', pady=8, padx=3)

        label = tk.Label(container, anchor='w', padx=3)
        label['font'] = ('sans', 10, 'bold underline')
        label['text'] = 'Type in your question'
        label.grid(column=1, row=0, sticky='new', pady=8, padx=3)

        values = []
        for item in self.db.view('modules'):
            values.append(item[1].title())

        string = tk.StringVar()

        self.combobox = ttk.Combobox(container)
        self.combobox['values'] = values
        self.combobox['state'] = 'readonly'
        self.combobox['cursor'] = 'hand2'
        self.combobox.grid(column=0, row=1, sticky='new', padx=3)
        self.combobox.bind('<<ComboboxSelected>>', partial(self.get_index, self.combobox))
        self.combobox.current(0)

        self.entry = ttk.Entry(container)
        self.entry['textvariable'] = string
        self.entry.grid(column=1, row=1, sticky='new', padx=3)

        label = tk.Label(container)
        label['text'] = 'Question List'
        label['font'] = ('sans', 12, 'bold')
        label.grid(column=0, row=2, columnspan=2, sticky='new', padx=3, pady=5)

        frame = tk.Frame(container)
        frame['bg'] = 'white'
        frame['borderwidth'] = 1
        frame['highlightcolor'] = 'black'
        frame['highlightbackground'] = 'black'
        frame['highlightthickness'] = 1
        frame.grid(column=0, row=3, columnspan=2, sticky='news', padx=3)
        frame.grid_columnconfigure(0, weight=3)

        self.listbox = tk.Listbox(frame)
        self.listbox['borderwidth'] = 0
        self.listbox['highlightcolor'] = 'white'
        self.listbox['highlightbackground'] = 'white'
        self.listbox['highlightthickness'] = 1
        self.listbox.grid(column=0, columnspan=2, row=2, sticky='news', padx=5, pady=5)


        label = tk.Label(container)
        label['text'] = 'Tip: Use mouse wheel to scroll list'
        label['bg'] = 'lightyellow'
        label['font'] = ('sans', 8, 'italic')
        label['relief'] = 'groove'
        label.grid(column=0, row=4, columnspan=2, sticky='new', padx=3, pady=5)

        btn_container = tk.Frame(container)
        btn_container.grid(column=0, row=5, columnspan=2, sticky='new', ipadx=3, pady=5)
        for i in range(4):
            btn_container.grid_columnconfigure(i, weight=3, uniform='buttons')

        buttons = {
        'Add': partial(self.add, string),
        'Edit': self.db.edit,
        'Delete': partial(self.delete),
        'Done': partial(self.done),
        }

        i = 0
        bgcolor = 'lightgray'
        fgcolor = 'black'
        for btn, command in buttons.items():
            if btn == 'Done':
                bgcolor = 'burlywood'
                fgcolor = 'brown'
            self.button = tk.Button(btn_container, text=btn, bg=bgcolor, fg=fgcolor)
            self.button['command'] = command
            self.button['cursor'] = 'hand2'
            self.button['font'] = ('sans', 10, 'normal')
            self.button.grid(column=i, row=0, sticky='new', padx=2)
            i += 1

            self.button.bind('<Enter>', partial(self.enter, self.button))
            self.button.bind('<Leave>', partial(self.leave, self.button))
        self.get_questions()

    def get_index(self, string, event):
        string = string.get().lower()
        id = self.db.get_id(string)
        id = id[0]
        self.get_questions(id=id)


    def delete(self):
        try:
            index = self.listbox.curselection()[0]
            question = self.listbox.get(index)
            self.db.delete(table='questions', question=question.lower())
            module = self.combobox.get()
            id = self.db.get_id(module.lower())
            self.get_questions(id=id[0])
        except:
            pass

    def get_questions(self, *args, id=1, **kwargs):
        self.listbox.delete(0, tk.END)
        for question in self.db.view('questions', id=id):
            self.listbox.insert(question[0], question[2])
        self.listbox.select_set(0)

    def enter(self, btn, event):
        if btn['text'].lower() == 'done':
            btn['bg'] = 'sandybrown'
            btn['fg'] = 'white'
            btn['font'] = ('sans', 10, 'bold')
        else:
            btn['bg'] = 'lightblue'
            btn['fg'] = 'mediumblue'
            btn['font'] = ('sans', 10, 'bold')

    def leave(self, btn, event):
        if btn['text'].lower() == 'done':
            btn['bg'] = 'burlywood'
            btn['fg'] = 'brown'
            btn['font'] = ('sans', 10, 'normal')
        else:
            btn['bg'] = 'lightgray'
            btn['fg'] = 'black'
            btn['font'] = ('sans', 10, 'normal')

    def add(self, string, *args, **kwargs):
        string = string.get().lower()
        module = self.combobox.get()
        id = self.db.get_id(module.lower())
        self.db.add(table=None, id=id[0], arg=string)
        self.entry.delete(0, tk.END)
        self.get_questions(id=id[0])

    def done(self):
        self.get_list(self.task)
        self.task.set('option1')
        self.window.deiconify()
        self.top.destroy()

# Class for setting up the add module window
class AddModule:
    def __init__(self, window, listbox, get_list, task):
        # Initiate the Database class, set some varibles from the main window
        # iconify the main window
        self.db = Database()
        self.window = window
        self.listbox = listbox
        self.get_list = get_list
        self.task = task
        window.iconify()

        # Create a toplevel window and form
        self.top = tk.Toplevel()
        self.top.title('Add a module')
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)
        self.top['padx'] = 5
        self.top['pady'] = 5
        self.top.geometry('400x100+250+250')
        self.top.resizable(False, False)

        self.container = tk.LabelFrame(self.top)
        self.container['text'] = 'Add a new module to the database'
        self.container.grid(column=0, row=0, sticky='news')
        self.container.grid_columnconfigure(1, weight=3)

        label = tk.Label(self.container)
        label['text'] = 'Module Name: '
        label.grid(column=0, row=0, sticky='new', padx=5, pady=8)

        module = tk.StringVar()
        style = ttk.Style()
        style.configure('TEntry', padding='5 1 5 1')
        self.entry = ttk.Entry(self.container, style='TEntry')
        self.entry['textvariable'] = module
        self.entry.focus_force()
        self.entry.grid(column=1, row=0, sticky='new', padx=5, pady=8)

        self.button = tk.Button(self.container, text='Submit')
        self.button['command'] = partial(self.add_module, self.entry)
        self.button['cursor'] = 'hand2'
        self.button['bg'] = 'lightgray'
        self.button.grid(column=1, row=1, columnspan=2, sticky='e', padx=5)
        self.entry.bind('<Return>', partial(self.add_module, self.entry))
        self.button.bind('<Enter>', self.enter)
        self.button.bind('<Leave>', self.leave)

    def enter(self, event):
        self.button['bg'] = 'lightblue'

    def leave(self, event):
        self.button['bg'] = 'lightgray'

    # Method for adding modules to the database, deiconify the main window and
    # destroy the top window
    def add_module(self, module, event=None):
        module = module.get()
        if module:
            self.db.add(table='modules', arg=module.lower())
            self.entry.delete(0, tk.END)
            self.listbox.delete(0, tk.END)
            self.get_list(self.task)
            self.window.deiconify()
            self.top.destroy()

        else:
            messagebox.showwarning('No Module Entered', 'Please type in a module name to add')

class Window:
    def __init__(self, parent):
        self.parent = parent
        self.parent.columnconfigure(0, weight=1)
        self.parent.rowconfigure(0, weight=1)

        # Initiate the Database class
        self.db = Database()

        self.task = tk.StringVar()
        self.task.set('option1')

        # Create a container for widgets
        self.container = tk.Frame(self.parent, padx=4, pady=2)
        self.container['borderwidth'] = 1
        self.container['highlightcolor'] = 'black'
        self.container['highlightbackground'] = 'black'
        self.container['highlightthickness'] = 1
        self.container.grid(column=0, row=0, sticky='new', pady=8, padx=8)
        self.container.grid_columnconfigure(0, weight=3)

        # Create the header
        header = tk.Label(self.container, text='Administration Tools')
        header['font'] = ('verdana', 16, 'bold')
        header['bg'] = 'lightgray'
        header.grid(column=0, row=0, sticky='new')

        # What operations do we want
        self.option = tk.LabelFrame(self.container, text='Choose a task')
        self.option.grid(column=0, row=1, sticky='new')
        self.option.grid_columnconfigure(0, weight=3, uniform='options')
        self.option.grid_columnconfigure(1, weight=3, uniform='options')

        self.option1 = tk.Radiobutton(self.option, text='Modules')
        self.option1['variable'] = self.task
        self.option1['value'] = 'option1'
        self.option1['command'] = partial(self.get_list, self.task)
        self.option1.grid(column=0, row=0, sticky='new')

        self.option2 = tk.Radiobutton(self.option, text='Questions')
        self.option2['variable'] = self.task
        self.option2['value'] = 'option2'
        self.option2['command'] = partial(self.add_window)
        self.option2.grid(column=1, row=0, sticky='new')

        # Create a listbox
        frame = tk.Frame(self.container, bg='white')
        frame['borderwidth'] = 1
        frame['highlightcolor'] = 'black'
        frame['highlightbackground'] = 'black'
        frame['highlightthickness'] = 1
        frame.grid(column=0, row=2, sticky='new', ipadx=5, ipady=5, pady=8)
        frame.grid_columnconfigure(0, weight=3)

        self.listbox = tk.Listbox(frame)
        self.listbox['borderwidth'] = 0
        self.listbox['highlightbackground'] = 'white'
        self.listbox['highlightcolor'] = 'white'
        self.listbox['selectmode'] = tk.SINGLE
        self.listbox.grid(column=0, row=0, sticky='news', padx=5, pady=5)

        # Populate the listbox on opening the window
        self.get_list(self.task)

    # Method to check if any modules exist. If so go to the questions window.
    # Otherwise stays on the modules window
    def add_window(self):
        if self.listbox.curselection():
            AddQuestion(self.parent, self.task, self.get_list)
        else:
            messagebox.showwarning('No Modules', 'You have to add at least one module to add questions.')
            self.task.set('option1')

    # Method for editing entries
    def edit(self, table, task):
        messagebox.showinfo('Edit', 'This method has not been programmed yet.')

    def delete(self, table, task):
        try:
            index = self.listbox.curselection()[0]
            confirm = messagebox.askokcancel('Delete Module', f'You are about to delete this module ( {self.listbox.get(index)} ).')
            if confirm:
                self.db.delete('modules', self.listbox.get(index).lower())
            else:
                pass
        except:
            pass

        # Updates the listbox
        self.get_list(task)

    # Method for changing button color on entring
    def enter(self, btn, event):
        if btn['text'].lower() == 'exit':
            btn['bg'] = 'red'
            btn['fg'] = 'white'
            btn['font'] = ('sans', 10, 'bold')
        else:
            btn['bg'] = 'lightblue'
            btn['fg'] = 'mediumblue'
            btn['font'] = ('sans', 10, 'bold')

    # Method for restoring button colors when exiting
    def leave(self, btn, event):
        if btn['text'].lower() == 'exit':
            btn['bg'] = 'tomato'
            btn['fg'] = 'black'
            btn['font'] = ('sans', 10, 'normal')
        else:
            btn['bg'] = 'lightgray'
            btn['fg'] = 'black'
            btn['font'] = ('sans', 10, 'normal')

    # Method for populating the listboxes
    # If option1 we want the modules else the questions
    def get_list(self, task):
        self.listbox.delete(0, tk.END)

        for item in self.db.view('modules'):
            self.listbox.insert(item[0], item[1].title())
        self.listbox.select_set(0)

        buttons = {
        'Add':partial(AddModule, self.parent, self.listbox, self.get_list, self.task),
        'Edit':partial(self.edit, 'modules', self.task),
        'Delete':partial(self.delete, 'modules', self.task),
        'Exit':sys.exit
        }

        # Create a container for the buttons
        btn_frame = tk.Frame(self.container)
        btn_frame.grid(column=0, row=3, sticky='new', pady=10)
        for btn in range(4):
            btn_frame.columnconfigure(btn, weight=3, uniform='buttons')

        # Control buttons and commands
        i = 0
        color = 'lightgray'
        for btn, command in buttons.items():
            if btn == 'Exit':
                color = 'tomato'
            self.button = tk.Button(btn_frame, bg=color)
            self.button['cursor'] = 'hand2'
            self.button['text'] = btn
            self.button['font'] = ('sans', 10, 'normal')
            self.button['command'] = command
            self.button.grid(column=i, row=0, sticky='new', padx=1)
            i += 1

            self.button.bind('<Enter>', partial(self.enter, self.button))
            self.button.bind('<Leave>', partial(self.leave, self.button))

def main():
    root = tk.Tk()
    root.title('Administration Tools')
    root.geometry('800x350+250+250')
    root['padx'] = 3
    root['pady'] = 5
    root.resizable(False, False)
    Window(root)
    root.mainloop()

main()
Reply
#20
Quick view of the pyqt5 version in the works
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
  [Tkinter] Error verify data in database TomasSanchexx 2 904 Aug-11-2023, 12:37 PM
Last Post: TomasSanchexx
  PyQt5 form not displaying my data from SQLite3 Database Linuxdesire 2 4,982 Jan-10-2023, 09:51 PM
Last Post: gradlon93
  [Tkinter] TKINTER quiz using sqlite3 database hezza_23 45 21,457 Nov-29-2021, 09:42 PM
Last Post: Hilal
  [Tkinter] load sqlite3 data into pdf rwahdan 5 4,364 Nov-29-2021, 07:58 PM
Last Post: Hilal
  Button to add data to database and listbox SalsaBeanDip 1 2,881 Dec-06-2020, 10:13 PM
Last Post: Larz60+
  Help with PySimpleGUI INSERT INTO sqlite3 database jrbond 5 7,173 Jul-20-2020, 01:24 PM
Last Post: jrbond
  [Tkinter] Displaying Data from a database and run a function when clicked? PythonNPC 1 2,070 Mar-11-2020, 08:16 PM
Last Post: Larz60+
  [Tkinter] I need to know how to put my SQLite3 data into a Treeview Thename921 1 7,118 Jan-12-2019, 10:26 PM
Last Post: Larz60+

Forum Jump:

User Panel Messages

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