Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Sqlite not updating
#1
I have a program that records score when practicing darts, then shows them in a high score table.
def addToDb(self):
        name = self.name
        total = self.runningTotal
        
        connection = sqlite3.connect('highscores.db')
        cur = connection.cursor()

        insert_statement = ''' INSERT INTO finisheshigh(playername, score) VALUES(?, ?); '''
        insert_values = (name, total)

        
        cur.execute(insert_statement, insert_values)
        print("done")
            

        connection.commit()
        cur.close()
I have this code which adds the result to the database.
And this code displays it.

        connection = sqlite3.connect('highscores.db')
        cur = connection.cursor()
        connection.commit()
        # populate rtb table
        read_query = '''SELECT * FROM rtbhigh ORDER BY score DESC'''
        cur.execute(read_query)
        items = cur.fetchall()

        tk.Label(frame1, text="Round the board").grid(row=0,column=0, columnspan=3)

        row = 1
        buttonnumber = 1 
        
        for item in items:
            fullframe = tk.Frame(frame1, highlightbackground="black", highlightthickness=1)
            fullframe.grid(row=row, column=0)
            tk.Label(fullframe, text=buttonnumber).grid(row=0, column=0)
            tk.Label(fullframe, text=item[0], width=20).grid(row=0, column=1)
            tk.Label(fullframe, text=item[1]).grid(row=0, column=2)
            row += 1 
            buttonnumber +=1

        #populate finishes table
        read_query = '''SELECT * FROM finisheshigh'''
        cur.execute(read_query)
        items = cur.fetchall()

        tk.Label(frame2, text="Finishes").grid(row=0,column=0, columnspan=3)

        row = 1
        buttonnumber = 1 

        for item in items:
            fullframe = tk.Frame(frame2, highlightbackground="black", highlightthickness=1)
            fullframe.grid(row=row, column=0)
            tk.Label(fullframe, text=buttonnumber).grid(row=0, column=0)
            tk.Label(fullframe, text=item[0], width=20).grid(row=0, column=1)
            tk.Label(fullframe, text=item[1]).grid(row=0, column=2)
            row += 1 
            buttonnumber +=1

        connection.commit()
        cur.close()
The issue I am having is the result which has just been input does not show in the displayed table, if the program is shut down then restarted it is there.
I have tried both cur.close and connection.close with no success.

Any help would be greatly appreciated.
Reply
#2
I took the liberty of giving your code a try. There is no data validation but, is a working model using classes. This could be improved upon.

import tkinter as tk
import sqlite3 as sq

class Database:
    '''
        Database class handles all database functions.
        Connects, creates, inserts, and get data
    '''
    def __init__(self):
        ''' Set some instance variables '''
        self.table = 'finisheshigh'
        self.connection = sq.connect('highscores.db')
        self.cursor = self.connection.cursor()

    def create(self):
        ''' Method for creating the table '''
        self.cursor.execute(f'''
            create table if not exists {self.table} (
            id integer primary key,
            playername text,
            score integer
            )
        ''')
        self.connection.commit()

    def insert(self, playername, score):
        ''' Method for inserting data '''
        self.cursor.execute(f'''
            insert into {self.table} (playername, score)
            values (?, ?)''', (playername, score))
        self.connection.commit()

    def getall(self):
        ''' Method for getting data '''
        self.cursor.execute(f'select * from {self.table} order by score desc')
        return self.cursor.fetchall()
    

class Window:
    '''
        Window class sets up the main window view
    '''
    def __init__(self, parent):
        self.parent = parent
        parent.columnconfigure(0, weight=1)
        parent.rowconfigure(0, weight=1)

        self.container = tk.Frame(parent)
        self.container.grid(column=0, row=0, sticky='news', padx=5, pady=5)
        self.container.grid_columnconfigure(0, weight=3, uniform='columns')
        self.container.grid_columnconfigure(1, weight=3, uniform='columns')

        header = tk.Label(self.container, text='Player', bg='lightgray')
        header['font'] = (None, 16, 'bold')
        header['relief'] = 'groove'
        header.grid(column=0, row=0, sticky='new', padx=(5,0), pady=(5,1))

        header2 = tk.Label(self.container, text='Score', bg='lightgray')
        header2['font'] = (None, 16, 'bold')
        header2['relief'] = 'groove'
        header2.grid(column=1, row=0, sticky='new', padx=(2,3), pady=(5,1))

        self.data_container = tk.Frame(self.container)
        self.data_container['relief'] = 'groove'
        self.data_container.grid(column=0, columnspan=2, row=1, sticky='new', padx=5, pady=(1,5))
        self.data_container.grid_columnconfigure(0, weight=3, uniform='columns')
        self.data_container.grid_columnconfigure(1, weight=3, uniform='columns')
        self.data_container.grid_columnconfigure(0, weight=3, uniform='data')
        self.data_container.grid_columnconfigure(1, weight=3, uniform='data')

        self.button = tk.Button(self.container, text='Add Entry')
        self.button['font'] = (None, 12, 'bold')
        self.button['cursor'] = 'hand2'
        self.button.grid(column=0, columnspan=2, row=3, ipadx=2, ipady=2)


class Form:
    ''' Form class builds and displays the form in a toplevel window '''
    def __init__(self, parent, getall):
        self.parent = parent
        self.getall = getall
        self.window = tk.Toplevel(None)
        self.window['padx'] = 10
        self.window['pady'] = 5
        self.window.title('Data Form')

        self.name = tk.StringVar()
        self.score = tk.StringVar()

        label = tk.Label(self.window, text='Name:', font=(None, 14, 'bold'))
        label.grid(column=0, row=0, sticky='new', pady=2)
        name = tk.Entry(self.window, textvariable=self.name, font=(None, 14, 'normal'))
        name.grid(column=1, row=0, sticky='new')

        label = tk.Label(self.window, text='Score:', font=(None, 14, 'bold'))
        label.grid(column=0, row=1, sticky='new', pady=2)
        score = tk.Entry(self.window, textvariable=self.score, font=(None, 14, 'normal'))
        score.grid(column=1, row=1, sticky='new')

        button = tk.Button(self.window, text='Submit', font=(None, 12, 'normal'))
        button['command'] = lambda: self.insert(self.name, self.score)
        button.grid(column=0, columnspan=2, row=2)

        self.window.protocol('WM_DELETE_WINDOW', self.close)

    def insert(self, name, score):
        ''' Method that inserts the data '''
        Database().insert(name.get(), score.get())
        self.close()

    def close(self):
        ''' A way to close the toplevel window and reopen the main window '''
        self.window.destroy()
        self.getall()
        self.parent.deiconify()


class Controller:
    '''
        Controller class communicates between the classes
    '''
    def __init__(self, database, window):
        # Set instance variables and populate the window if data exists
        self.database = database
        self.database.create()
        self.window = window
        self.getall()

        # Command for the window button to open toplevel window
        self.window.button['command'] = self._window

    def _window(self):
        ''' Method for withdrawing main window and opoening toplevel window '''
        self.window.parent.withdraw()
        form = Form(self.window.parent, self.getall)

    def getall(self):
        '''
         This method could be improved on
        '''
        stats = self.database.getall() # Get database entries

        # This will destroy and rebuild the data container in the main window.
        # Reasoning was that trace data was still visible after entering data
        self.window.data_container.destroy()
        self.window.data_container = tk.Frame(self.window.container)
        self.window.data_container['relief'] = 'groove'
        self.window.data_container.grid(column=0, columnspan=2, row=1, sticky='new', padx=5, pady=(1,5))
        self.window.data_container.grid_columnconfigure(0, weight=3, uniform='columns')
        self.window.data_container.grid_columnconfigure(1, weight=3, uniform='columns')
        self.window.data_container.grid_columnconfigure(0, weight=3, uniform='data')
        self.window.data_container.grid_columnconfigure(1, weight=3, uniform='data')

        # if there is no data display a message stating so else populate
        if not stats:
            label = tk.Label(self.window.data_container)
            label['text'] = 'Currently, there are not any stats recorded.'
            label['fg'] = 'red'
            label['font'] = (None, 14, 'normal')
            label['relief'] = 'ridge'
            label.grid(column=0, columnspan=2, row=0, sticky='new', ipadx=5)
        else:
            for row, data in enumerate(self.database.getall()):
                label = tk.Label(self.window.data_container)
                label['font'] = (None, 14, 'normal')
                label['text'] = data[1].title()
                label['relief'] = 'ridge'
                label.grid(column=0, row=row, sticky='new', padx=(0,1), pady=2)

                label = tk.Label(self.window.data_container)
                label['font'] = (None, 14, 'normal')
                label['text'] = data[2]
                label['relief'] = 'ridge'
                label.grid(column=1, row=row, sticky='new', padx=(1,0), pady=2)

            


if __name__ == '__main__':
    root = tk.Tk()
    controller = Controller(Database(), Window(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
#3
(May-24-2023, 04:37 AM)angus1964 Wrote: I have a program that records score when practicing darts, then shows them in a high score table.
def addToDb(self):
        name = self.name
        total = self.runningTotal
        
        connection = sqlite3.connect('highscores.db')
        cur = connection.cursor()

        insert_statement = ''' INSERT INTO finisheshigh(playername, score) VALUES(?, ?); '''
        insert_values = (name, total)

        
        cur.execute(insert_statement, insert_values)
        print("done")
            

        connection.commit()
        cur.close()
I have this code which adds the result to the database.
And this code displays it.

        connection = sqlite3.connect('highscores.db')
        cur = connection.cursor()
        connection.commit()
        # populate rtb table
        read_query = '''SELECT * FROM rtbhigh ORDER BY score DESC'''
        cur.execute(read_query)
        items = cur.fetchall()

        tk.Label(frame1, text="Round the board").grid(row=0,column=0, columnspan=3)

        row = 1
        buttonnumber = 1 
        
        for item in items:
            fullframe = tk.Frame(frame1, highlightbackground="black", highlightthickness=1)
            fullframe.grid(row=row, column=0)
            tk.Label(fullframe, text=buttonnumber).grid(row=0, column=0)
            tk.Label(fullframe, text=item[0], width=20).grid(row=0, column=1)
            tk.Label(fullframe, text=item[1]).grid(row=0, column=2)
            row += 1 
            buttonnumber +=1

        #populate finishes table
        read_query = '''SELECT * FROM finisheshigh'''
        cur.execute(read_query)
        items = cur.fetchall()

        tk.Label(frame2, text="Finishes").grid(row=0,column=0, columnspan=3)

        row = 1
        buttonnumber = 1 

        for item in items:
            fullframe = tk.Frame(frame2, highlightbackground="black", highlightthickness=1)
            fullframe.grid(row=row, column=0)
            tk.Label(fullframe, text=buttonnumber).grid(row=0, column=0)
            tk.Label(fullframe, text=item[0], width=20).grid(row=0, column=1)
            tk.Label(fullframe, text=item[1]).grid(row=0, column=2)
            row += 1 
            buttonnumber +=1

        connection.commit()
        cur.close()
The issue I am having is the result which has just been input does not show in the displayed table, if the program is shut down then restarted it is there.
I have tried both cur.close and connection.close with no success.

Any help would be greatly appreciated.

Hi Menator thats very helpful. You are correct about the data validation, I was hoping to get the basics working before looking at the bells and whistles.

Here is the full code.
import tkinter as tk
from tkinter import ttk
import sqlite3


class practice(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        # Adding a title to the window
        self.wm_title("Test Application")

        # creating a frame and assigning it to container
        container = tk.Frame(self, height=400, width=600)
        # specifying the region where the frame is packed in root
        container.pack(side="top", fill="both", expand=True)

        # configuring the location of the container using grid
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.menu = tk.Menu(container, bg="lightgrey", fg="black")
        # first menu item
        self.game_menu = tk.Menu(self.menu, tearoff=0, bg="lightgrey", fg="black")
        self.game_menu.add_command(label="New Game", command=lambda: self.show_frame(RtbPage),)
        self.menu.add_cascade(label="Round the board", menu=self.game_menu)

        # second menu item
        self.stat_menu = tk.Menu(self.menu, tearoff=0, bg="lightgrey", fg="black")
        self.stat_menu.add_command(label="New Game", command=lambda: self.show_frame(FinishesPage))
        self.menu.add_cascade(label="Finishes", menu=self.stat_menu)

        # third menu item
        self.stat_menu = tk.Menu(self.menu, tearoff=0, bg="lightgrey", fg="black")
        self.stat_menu.add_command(label="High Scores", command=lambda: self.show_frame(HighScoresPage))
        self.menu.add_cascade(label="High Scores", menu=self.stat_menu)

        # populate the menu
        self.config(menu=self.menu)

     # We will now create a dictionary of frames
        self.frames = {}
        # we'll create the frames themselves later but let's add the components to the dictionary.
        for F in (StartPage, RtbPage, FinishesPage, HighScoresPage):
            frame = F(container, self)

            # the windows class acts as the root window for the frames.
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        # Using a method to switch frames
        self.show_frame(StartPage)
        self.db_connect()

    def show_frame(self, cont):
        frame = self.frames[cont]
        # raises the current frame to the top
        frame.tkraise()

    def db_connect(self):
        connection = sqlite3.connect('highscores.db')
        cur = connection.cursor()

        try:
            cur.execute('SELECT * FROM rtbhigh')

        except sqlite3.OperationalError:
            cur.execute(''' CREATE TABLE rtbhigh(playername text, score integer) ''')
            cur.execute(''' CREATE TABLE finisheshigh(playername text, score integer) ''')

        connection.commit()
        cur.close()



class StartPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Main Page")
        label.pack(padx=10, pady=10)


class RtbPage(tk.Frame):
    def __init__(self, parent, controller   ):
        tk.Frame.__init__(self, parent)

        #variables
        self.playerName = tk.StringVar()
        self.toGoFor = 1
        self.runningTotal = 0
        self.goFor = tk.IntVar()
        self.goFor.set(self.toGoFor)
        self.running = tk.IntVar()
        self.running.set(self.runningTotal)
        


        frame1 = tk.Frame(self)
        frame1.grid(row=0, column=0, sticky='nsew')
        namelabel = tk.Label(frame1, text="Player Name: ")
        namelabel.grid(row=0, column=0, sticky='ew')
        nameEntry = tk.Entry(frame1, textvariable=self.playerName)
        nameEntry.grid(row=0, column=1, sticky='ew')
        startButton = tk.Button(frame1, text="Start", command=self.show_frame2)
        startButton.grid(row=0, column=2, sticky='ew')

    def show_frame2(self):
        self.name = self.playerName.get()
        frame2 = tk.Frame(self)
        frame2.grid(row=1, column=0, sticky='nsew')
        togoforLabel = tk.Label(frame2, text="To Go For:")
        togoforLabel.grid(row=0, column=0, sticky='nsew')
        numberLabel = tk.Label(frame2, textvariable=self.goFor)
        numberLabel.grid(row=1, column=0, sticky='nsew')
        hitLabel = tk.Label(frame2, text="Enter Number Hit:")
        hitLabel.grid(row=0, column=1)
        self.hitCombo = ttk.Combobox(frame2, width = 15)
        self.hitCombo.grid(row=1, column=1, sticky='nsew')
        self.hitCombo['values'] = (0, 1, 2, 3,4,5,6, 7,8,9)
        #self.hitCombo.bind('<<ComboboxSelected>>', self.score_entered)
        self.hitCombo.bind('<Return>', self.score_entered)
        scoreButton = tk.Button(frame2, text=" Enter: ", command=self.score_entered)
        scoreButton.grid(row=2, column=1)
        
        totalLabel = tk.Label(frame2, text="Running Total : ")
        totalLabel.grid(row=0, column=2, sticky='nsew')
        runningLabel = tk.Label(frame2, textvariable=self.running)
        runningLabel.grid(row=1, column=2, sticky='nsew')


    def score_entered(self):
        score = int(self.hitCombo.get())
        subTotal = score * self.toGoFor
        self.runningTotal += subTotal
        self.toGoFor += 1
        if self.toGoFor == 21:
            self.toGoFor = 25
        if self.toGoFor == 5:
            self.running.set(self.runningTotal)
            self.gameFinished()
        else:
            self.goFor.set(self.toGoFor)
            self.running.set(self.runningTotal)
        
            self.hitCombo.set('')
        

    def gameFinished(self):
        frame3 = tk.Frame(self)
        frame3.grid(row=2, column=0, sticky='nsew')
        overLabel = tk.Label(frame3, text="Game Over: Your Total is: ")
        overLabel.grid(row=0, column=0, sticky='nsew')
        totalLabel = tk.Label(frame3, textvariable=self.running)
        totalLabel.grid(row=0, column=1, sticky='nsew')
        saveButton = tk.Button(frame3, text="Save", command=self.addToDb)
        saveButton.grid(row=0, column=2, sticky='nsew')

    def addToDb(self):
        name = self.name
        total = self.runningTotal
        
        connection = sqlite3.connect('highscores.db')
        cur = connection.cursor()

        insert_statement = ''' INSERT INTO rtbhigh(playername, score) VALUES(?, ?); '''
        insert_values = (name, total)

        
        cur.execute(insert_statement, insert_values)
        print("done")
            

        connection.commit()
        cur.close()
        


class FinishesPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        #variables
        self.toGoFor = 61
        self.runningTotal = 0
        self.goFor = tk.IntVar()
        self.goFor.set(self.toGoFor)
        self.running = tk.IntVar()
        self.running.set(self.runningTotal)
        self.playerName = tk.StringVar()


        frame1 = tk.Frame(self)
        frame1.grid(row=0, column=0, sticky='nsew')
        namelabel = tk.Label(frame1, text="Player Name: ")
        namelabel.grid(row=0, column=0, sticky='ew')
        nameEntry = tk.Entry(frame1, textvariable=self.playerName)
        nameEntry.grid(row=0, column=1, sticky='ew')
        startButton = tk.Button(frame1, text="Start", command=self.show_frame2)
        startButton.grid(row=0, column=2, sticky='ew')

    def show_frame2(self):
        self.name = self.playerName.get()
        frame2 = tk.Frame(self)
        frame2.grid(row=1, column=0, sticky='nsew')
        togoforLabel = tk.Label(frame2, text="To Go For:")
        togoforLabel.grid(row=0, column=0, sticky='nsew')
        numberLabel = tk.Label(frame2, textvariable=self.goFor)
        numberLabel.grid(row=1, column=0, sticky='nsew')
        hitLabel = tk.Label(frame2, text="Number of darts used:")
        hitLabel.grid(row=0, column=1)
        self.hitCombo = ttk.Combobox(frame2, width = 15)
        self.hitCombo.grid(row=1, column=1, sticky='nsew')
        self.hitCombo['values'] = (2,3,4,5,6,0)
        self.hitCombo.bind('<<ComboboxSelected>>')
        scoreButton = tk.Button(frame2, text=" Enter: ", command=self.score_entered)
        scoreButton.grid(row=2, column=1)
        totalLabel = tk.Label(frame2, text="Running Total : ")
        totalLabel.grid(row=0, column=2, sticky='nsew')
        runningLabel = tk.Label(frame2, textvariable=self.running)
        runningLabel.grid(row=1, column=2, sticky='nsew')


    def score_entered(self):
        darts = int(self.hitCombo.get())
        if self.toGoFor == 99:
            if darts == 0:
                self.runningTotal += 0
            elif darts == 3:
                self.runningTotal += 3
            elif darts == 4 or 5 or 6:
                self.runningTotal += 1
            
        else:
            if darts == 0:
                self.runningTotal += 0
            elif darts == 2:
                self.runningTotal += 3
            elif darts == 3:
                self.runningTotal += 2
            elif darts == 4 or 5 or 6:
                self.runningTotal += 1
            self.running.set(self.runningTotal)
            self.toGoFor += 1
            if self.toGoFor == 63:
                self.gameFinished()
            else:
                self.goFor.set(self.toGoFor)
                self.hitCombo.set('')
        

    def gameFinished(self):
        frame3 = tk.Frame(self)
        frame3.grid(row=2, column=0, sticky='nsew')
        overLabel = tk.Label(frame3, text="Game Over: Your Total is: ")
        overLabel.grid(row=0, column=0, sticky='nsew')
        tk.Label(frame3, text=self.runningTotal).grid(row=0,column=1, sticky='nsew')
        saveButton = tk.Button(frame3, text="Save", command=self.addToDb)
        saveButton.grid(row=0, column=2, sticky='nsew')

    def addToDb(self):
        name = self.name
        total = self.runningTotal
        
        connection = sqlite3.connect('highscores.db')
        cur = connection.cursor()

        insert_statement = ''' INSERT INTO finisheshigh(playername, score) VALUES(?, ?); '''
        insert_values = (name, total)

        
        cur.execute(insert_statement, insert_values)
        print("done")
            

        connection.commit()
        cur.close()

        

        


    



class HighScoresPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        frame1 = tk.Frame(self)
        frame1.grid(row=0, column=0, sticky='nsew')
        frame2 = tk.Frame(self)
        frame2.grid(row=0, column=1, sticky='nsew')

        connection = sqlite3.connect('highscores.db')
        cur = connection.cursor()
        connection.commit()
        # populate rtb table
        read_query = '''SELECT * FROM rtbhigh ORDER BY score DESC'''
        cur.execute(read_query)
        items = cur.fetchall()

        tk.Label(frame1, text="Round the board").grid(row=0,column=0, columnspan=3)

        row = 1
        buttonnumber = 1 
        
        for item in items:
            fullframe = tk.Frame(frame1, highlightbackground="black", highlightthickness=1)
            fullframe.grid(row=row, column=0)
            tk.Label(fullframe, text=buttonnumber).grid(row=0, column=0)
            tk.Label(fullframe, text=item[0], width=20).grid(row=0, column=1)
            tk.Label(fullframe, text=item[1]).grid(row=0, column=2)
            row += 1 
            buttonnumber +=1

        #populate finishes table
        read_query = '''SELECT * FROM finisheshigh'''
        cur.execute(read_query)
        items = cur.fetchall()

        tk.Label(frame2, text="Finishes").grid(row=0,column=0, columnspan=3)

        row = 1
        buttonnumber = 1 

        for item in items:
            fullframe = tk.Frame(frame2, highlightbackground="black", highlightthickness=1)
            fullframe.grid(row=row, column=0)
            tk.Label(fullframe, text=buttonnumber).grid(row=0, column=0)
            tk.Label(fullframe, text=item[0], width=20).grid(row=0, column=1)
            tk.Label(fullframe, text=item[1]).grid(row=0, column=2)
            row += 1 
            buttonnumber +=1

        connection.commit()
        cur.close()




        
        

    

if __name__ == "__main__":
    game = practice()
    game.mainloop()
Reply
#4
I tried running your code, the database was created but not the tables.
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#5
(May-24-2023, 06:42 PM)menator01 Wrote: I took the liberty of giving your code a try. There is no data validation but, is a working model using classes. This could be improved upon.

import tkinter as tk
import sqlite3 as sq

class Database:
    '''
        Database class handles all database functions.
        Connects, creates, inserts, and get data
    '''
    def __init__(self):
        ''' Set some instance variables '''
        self.table = 'finisheshigh'
        self.connection = sq.connect('highscores.db')
        self.cursor = self.connection.cursor()

    def create(self):
        ''' Method for creating the table '''
        self.cursor.execute(f'''
            create table if not exists {self.table} (
            id integer primary key,
            playername text,
            score integer
            )
        ''')
        self.connection.commit()

    def insert(self, playername, score):
        ''' Method for inserting data '''
        self.cursor.execute(f'''
            insert into {self.table} (playername, score)
            values (?, ?)''', (playername, score))
        self.connection.commit()

    def getall(self):
        ''' Method for getting data '''
        self.cursor.execute(f'select * from {self.table} order by score desc')
        return self.cursor.fetchall()
    

class Window:
    '''
        Window class sets up the main window view
    '''
    def __init__(self, parent):
        self.parent = parent
        parent.columnconfigure(0, weight=1)
        parent.rowconfigure(0, weight=1)

        self.container = tk.Frame(parent)
        self.container.grid(column=0, row=0, sticky='news', padx=5, pady=5)
        self.container.grid_columnconfigure(0, weight=3, uniform='columns')
        self.container.grid_columnconfigure(1, weight=3, uniform='columns')

        header = tk.Label(self.container, text='Player', bg='lightgray')
        header['font'] = (None, 16, 'bold')
        header['relief'] = 'groove'
        header.grid(column=0, row=0, sticky='new', padx=(5,0), pady=(5,1))

        header2 = tk.Label(self.container, text='Score', bg='lightgray')
        header2['font'] = (None, 16, 'bold')
        header2['relief'] = 'groove'
        header2.grid(column=1, row=0, sticky='new', padx=(2,3), pady=(5,1))

        self.data_container = tk.Frame(self.container)
        self.data_container['relief'] = 'groove'
        self.data_container.grid(column=0, columnspan=2, row=1, sticky='new', padx=5, pady=(1,5))
        self.data_container.grid_columnconfigure(0, weight=3, uniform='columns')
        self.data_container.grid_columnconfigure(1, weight=3, uniform='columns')
        self.data_container.grid_columnconfigure(0, weight=3, uniform='data')
        self.data_container.grid_columnconfigure(1, weight=3, uniform='data')

        self.button = tk.Button(self.container, text='Add Entry')
        self.button['font'] = (None, 12, 'bold')
        self.button['cursor'] = 'hand2'
        self.button.grid(column=0, columnspan=2, row=3, ipadx=2, ipady=2)


class Form:
    ''' Form class builds and displays the form in a toplevel window '''
    def __init__(self, parent, getall):
        self.parent = parent
        self.getall = getall
        self.window = tk.Toplevel(None)
        self.window['padx'] = 10
        self.window['pady'] = 5
        self.window.title('Data Form')

        self.name = tk.StringVar()
        self.score = tk.StringVar()

        label = tk.Label(self.window, text='Name:', font=(None, 14, 'bold'))
        label.grid(column=0, row=0, sticky='new', pady=2)
        name = tk.Entry(self.window, textvariable=self.name, font=(None, 14, 'normal'))
        name.grid(column=1, row=0, sticky='new')

        label = tk.Label(self.window, text='Score:', font=(None, 14, 'bold'))
        label.grid(column=0, row=1, sticky='new', pady=2)
        score = tk.Entry(self.window, textvariable=self.score, font=(None, 14, 'normal'))
        score.grid(column=1, row=1, sticky='new')

        button = tk.Button(self.window, text='Submit', font=(None, 12, 'normal'))
        button['command'] = lambda: self.insert(self.name, self.score)
        button.grid(column=0, columnspan=2, row=2)

        self.window.protocol('WM_DELETE_WINDOW', self.close)

    def insert(self, name, score):
        ''' Method that inserts the data '''
        Database().insert(name.get(), score.get())
        self.close()

    def close(self):
        ''' A way to close the toplevel window and reopen the main window '''
        self.window.destroy()
        self.getall()
        self.parent.deiconify()


class Controller:
    '''
        Controller class communicates between the classes
    '''
    def __init__(self, database, window):
        # Set instance variables and populate the window if data exists
        self.database = database
        self.database.create()
        self.window = window
        self.getall()

        # Command for the window button to open toplevel window
        self.window.button['command'] = self._window

    def _window(self):
        ''' Method for withdrawing main window and opoening toplevel window '''
        self.window.parent.withdraw()
        form = Form(self.window.parent, self.getall)

    def getall(self):
        '''
         This method could be improved on
        '''
        stats = self.database.getall() # Get database entries

        # This will destroy and rebuild the data container in the main window.
        # Reasoning was that trace data was still visible after entering data
        self.window.data_container.destroy()
        self.window.data_container = tk.Frame(self.window.container)
        self.window.data_container['relief'] = 'groove'
        self.window.data_container.grid(column=0, columnspan=2, row=1, sticky='new', padx=5, pady=(1,5))
        self.window.data_container.grid_columnconfigure(0, weight=3, uniform='columns')
        self.window.data_container.grid_columnconfigure(1, weight=3, uniform='columns')
        self.window.data_container.grid_columnconfigure(0, weight=3, uniform='data')
        self.window.data_container.grid_columnconfigure(1, weight=3, uniform='data')

        # if there is no data display a message stating so else populate
        if not stats:
            label = tk.Label(self.window.data_container)
            label['text'] = 'Currently, there are not any stats recorded.'
            label['fg'] = 'red'
            label['font'] = (None, 14, 'normal')
            label['relief'] = 'ridge'
            label.grid(column=0, columnspan=2, row=0, sticky='new', ipadx=5)
        else:
            for row, data in enumerate(self.database.getall()):
                label = tk.Label(self.window.data_container)
                label['font'] = (None, 14, 'normal')
                label['text'] = data[1].title()
                label['relief'] = 'ridge'
                label.grid(column=0, row=row, sticky='new', padx=(0,1), pady=2)

                label = tk.Label(self.window.data_container)
                label['font'] = (None, 14, 'normal')
                label['text'] = data[2]
                label['relief'] = 'ridge'
                label.grid(column=1, row=row, sticky='new', padx=(1,0), pady=2)

            


if __name__ == '__main__':
    root = tk.Tk()
    controller = Controller(Database(), Window(root))
    root.mainloop()


Hi Menator, did give your code a try and got the following error.

Quote:Traceback (most recent call last):
File "/Users/angusgalbraith/Library/CloudStorage/OneDrive-Personal/Programming/Darts/Python/web.py", line 181, in <module>
controller = Controller(Database(), Window(root))
File "/Users/angusgalbraith/Library/CloudStorage/OneDrive-Personal/Programming/Darts/Python/web.py", line 127, in __init__
self.getall()
File "/Users/angusgalbraith/Library/CloudStorage/OneDrive-Personal/Programming/Darts/Python/web.py", line 166, in getall
label['text'] = data[1].title()
AttributeError: 'int' object has no attribute 'title'
Will have a better look in the morning, lots of good things I will take from your code

Many Thanks

Angus
menator01 likes this post
Reply
#6
You can remove the .title() part. It just capitalizes the returned names
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#7
(May-24-2023, 07:02 PM)menator01 Wrote: I tried running your code, the database was created but not the tables.

It worked OK on mine, will try running from scratch again tomorrow.
Reply
#8
(May-24-2023, 07:02 PM)menator01 Wrote: I tried running your code, the database was created but not the tables.

Hi Menator
I moved the call to create the db to just below menu creation, and it works fine now, not a great way to do it, will investigates your class method.
Still have the original issue, did wonder if it was due to files being on cloud but when run locally same issue. Hoping once class built it will solve it.
Have managed to work out when you click the save button it is added to the database, I checked from the terminal. So it would appear the issue is getting the full data to populate the table.

Confused
Reply
#9
SQLalchemy makes working with databases very straight forward and maintainable.
If interested, I have a tutorial (a bit old but should still be good) here.
Reply
#10
(May-25-2023, 10:16 PM)Larz60+ Wrote: SQLalchemy makes working with databases very straight forward and maintainable.
If interested, I have a tutorial (a bit old but should still be good) here.

Hi Larz
Will have a look at SQLalchemy, would be nice to know why I have the issue I have just in case I have made a fundamental mistake and just not realised.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Updating records 1 to n on an SQLite table KevinBrown 2 2,660 Mar-30-2019, 05:02 PM
Last Post: KevinBrown

Forum Jump:

User Panel Messages

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