Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Sqlite not updating
#21
(May-31-2023, 06:37 AM)angus1964 Wrote:
(May-31-2023, 06:11 AM)menator01 Wrote: From my earlier example. On the rtb page I've placed two buttons. One will raise the main page and the other will raise the finish page.

import tkinter as tk
import sqlite3 as sq
 
class Database:
    '''
        Database class handles all the database functions.
        Create, insert, and retrieve
    '''
    def __init__(self):
        self.tables = ('rtbhigh', 'finisheshigh')
        self.connection = sq.connect('highscores.db')
        self.cursor = self.connection.cursor()
 
    def create_tables(self):
        self.cursor.execute('''
            create table if not exists rtbhigh (
            playername text, score integer
            )
        ''')
 
        self.cursor.execute('''
            create table if not exists finisheshigh (
            playername text, score integer
            )
        ''')
        self.connection.commit()
 
 
    def insert(self, playername, score, table):
        self.cursor.execute(f'insert into {table} (playername, score) values(?,?)', (playername, score))
        self.connection.commit()
             
    def getall(self, table):
        query = self.cursor.execute(f'select * from {table} order by score desc').fetchall()
        print(query)
        return query
 
 
class Rtb(tk.Frame):
    def __init__(self):
        tk.Frame.__init__(self)
        self.grid_columnconfigure(0, weight=3, uniform='btns')
        self.grid_columnconfigure(1, weight=3, uniform='btns')
        
        label = tk.Label(self, text='Rtb Page', bg='pink')
        label.grid(column=0, row=0, columnspan=2, sticky='news')

        self.button = tk.Button(self, text='Raise Main Page')
        self.button.grid(column=0, row=1, sticky='new', padx=2)

        self.button2 = tk.Button(self, text='Raise Finish Page')
        self.button2.grid(column=1, row=1, sticky='new', padx=2)
 
 
class Main(tk.Frame):
    ''' Main class is the start/landing page '''
    def __init__(self):
        tk.Frame.__init__(self)
        label = tk.Label(self, text='Main Page', bg='gold')
        label.grid(column=0, row=0, sticky='news')
 
 
class Finish(tk.Frame):
    def __init__(self):
        tk.Frame.__init__(self)
        label = tk.Label(self, text='Finish Page', bg='tomato')
        label.grid(column=0, row=0, sticky='news')
 
 
class HighScore(tk.Frame):
    '''
        HighScores class displays all scores
    '''
    def __init__(self, data):
        tk.Frame.__init__(self)
        container = tk.Frame(self)
        container.grid(column=0, row=0, sticky='new')
        container.grid_columnconfigure(0, weight=3)
 
        header = tk.Label(container, text='High Scores', bg='gray')
        header['font'] = (None, 18, 'bold')
        header['highlightbackground'] = 'black'
        header['highlightcolor'] = 'black'
        header['highlightthickness'] = 1
        header.grid(column=0, row=0, sticky='new', padx=3, pady=(0, 8))
 
        row = 1
        for name, score in data:
            label = tk.Label(container, text=f'{name.title()}: {score}', bg='lightgray', anchor='w', padx=8)
            label['font'] = (None, 14, 'normal')
            label['highlightbackground'] = 'black'
            label['highlightcolor'] = 'black'
            label['highlightthickness'] = 1
            label.grid(column=0, row=row, sticky='new', ipadx=5, padx=3)
            row += 1
 
 
class NewGame(tk.Frame):
    ''' NewGame class page for starting new games '''
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        label = tk.Label(self, text='Start a new game', bg='burlywood')
        label['font'] = (None, 16, 'normal')
        label.grid(column=0, row=0, sticky='new')
 
 
class Window(tk.Frame):
    ''' Window class is for the menus and container'''
    def __init__(self, parent):
        self.parent = parent
        tk.Frame.__init__(self, parent)
        parent.title('Test Application')
        parent.columnconfigure(0, weight=1)
        parent.rowconfigure(0, weight=1)
 
        self.menubar = tk.Menu(parent)
        parent.configure(menu=self.menubar)
 
 
 
class Controller:
    ''' Controller class ties all the classes together '''
    def __init__(self, database, window):
        self.db = database
        self.window = window
        self.db.create_tables()
        # self.db.insert('john doe', 15, self.db.tables[1])
        # self.db.insert('jane doe', 25, self.db.tables[1])
        # self.db.insert('child doe', 5, self.db.tables[1])
         
 
        # Setup the pages by calling the appropiate class
        page2 = Rtb()
        page2.grid(column=0, row=0, sticky='news')
        page2.grid_columnconfigure(0, weight=3)
        page2.grid_rowconfigure(0, weight=3)
 
        page3 = Finish()
        page3.grid(column=0, row=0, sticky='news')
        page3.grid_columnconfigure(0, weight=3)
        page3.grid_rowconfigure(0, weight=3)
 
        page4 = HighScore(self.get_scores())
        page4.grid(column=0, row=0, sticky='news')
        page4.grid_columnconfigure(0, weight=3)
        page4.grid_rowconfigure(0, weight=3)
 
        page5 = NewGame()
        page5.grid(column=0, row=0, sticky='news')
        page5.grid_columnconfigure(0, weight=3)
        page5.grid_rowconfigure(0, weight=3)
 
        page1 = Main()
        page1.grid(column=0, row=0, sticky='news')
        page1.grid_columnconfigure(0, weight=3)
        page1.grid_rowconfigure(0, weight=3)
 
        # Setup the menus and commands
        game_menu = tk.Menu(self.window.menubar, tearoff=0)
        game_menu.add_command(label='New Game', command=page5.tkraise)
        game_menu.add_separator()
        game_menu.add_command(label='Exit', command=self.window.parent.destroy)
 
        page_menu = tk.Menu(self.window.menubar, tearoff=0)
        page_menu.add_command(label='Main Page', command=page1.tkraise)
        page_menu.add_command(label='RTB Page', command=page2.tkraise)
        page_menu.add_command(label='Finish Page', command=page3.tkraise)
        page_menu.add_command(label='High Scores', command=page4.tkraise)
 
        page_menu.add_separator()
        page_menu.add_command(label='Exit', command=self.window.parent.destroy)
 
        self.window.menubar.add_cascade(label='Game Options', menu=game_menu)
        self.window.menubar.add_cascade(label='Pages', menu=page_menu)

        page2.button['command'] = page1.tkraise
        page2.button2['command'] = page3.tkraise
 
    def get_scores(self):
        ''' Method for getting scores '''
        data = self.db.getall(self.db.tables[1])
        print(data)
        return data
 
 
if __name__ == '__main__':
    root = tk.Tk()
    root.geometry('600x400+300+300')
    controller = Controller(Database(), Window(root))
    root.mainloop()

Many thanks, so obvious now I see it.
Good example of why not to look at it at night, when your knackered. Cool

Menator - Just a quick question, If I wanted to reuse one of the pages i.e a new game. Would it be as simple as creating another instance of the class with the same name or will I need to clear the frames manually and repopulate?
Reply
#22
The HighScores window is not written correctly. When the data page is drawn, it should query the database and update the scores. You could do this by deleting all the old labels, and creating new, or you could select a widget that is designed to display tabular information.

This demonstrates calling a function to update the high score window and then display the scores.
import tkinter as tk


class Page(tk.Frame):
    """A frame to be displayed in a stacked frame."""
    def __init__(self, parent, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.grid(row=0, column=0, sticky="news")
        self.connection = None

    def connect(self, function):
        """Provide a callback for the page."""
        self.connection = function

    def show(self):
        """Display this page."""
        self.tkraise()


class Game(Page):
    """Pretend game.  Enter your score and press button"""
    def __init__(self, *args, **kwargs):
        super().__init__(self, *args, **kwargs)
        font = (None, 24)
        self.name = tk.StringVar(self, "")
        self.score = tk.StringVar(self, "")
        name_label = tk.Label(self, text="Name", font=font)
        score_label = tk.Label(self, text="Score", font=font)
        name_entry = tk.Entry(self, textvariable=self.name, width=10, font=font)
        score_entry = tk.Entry(self, textvariable=self.score, width=4, font=font)
        button = tk.Button(self, text="Enter Score", font=font, command=self.game_over)
        name_label.grid(row=0, column=0, padx=5, pady=5)
        name_entry.grid(row=0, column=1, padx=5, pady=5)
        score_label.grid(row=1, column=0, padx=5, pady=5)
        score_entry.grid(row=1, column=1, padx=5, pady=5)
        button.grid(row=2, column=0, columnspan=2)

    def game_over(self):
        """Button callback.  Calls connection."""
        if self.connection:
            self.connection(self.name.get(), int(self.score.get()))

    def show(self):
        """Reset entries and display."""
        self.name.set("")
        self.score.set("")
        super().show()


class HighScore(Page):
    """Page that displays high score table."""
    def __init__(self, *args, **kwargs):
        super().__init__(self, *args, **kwargs)
        self.scores = [tk.StringVar(self, "") for _ in range(10)]
        bg = self["bg"]
        label = tk.Label(self, text="High Scores", bg=bg, font=(None, 24))
        label.grid(row=0, column=0)
        for row, score in enumerate(self.scores, start=1):
            label = tk.Label(self, textvariable=score, width=20, bg=bg, font=(None, 20))
            label.grid(row=row, column=0)
        button = tk.Button(
            self, text="Play Again?", bg=bg, command=self.play_again, font=(None, 20)
        )
        button.grid(row=row, column=0, padx=5, pady=5)

    def play_again(self):
        """Called when play again button pressed."""
        if self.connection:
            self.connection()

    def show(self, high_scores):
        """Update scores and display."""
        for var in self.scores:
            var.set("")
        for (score, name), var in zip(high_scores, self.scores):
            var.set(f"{name:14} {score:5}")
        super().show()


class MainWindow(tk.Tk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.high_scores = [(123, "Jimbo"), (950, "Billy"), (593, "Sassy")]
        pages = tk.Frame(self)
        pages.pack(expand=True, fill=tk.BOTH)
        self.game = Game(pages)
        self.game.connect(self.game_over)
        self.high_score = HighScore(pages)
        self.high_score.connect(self.game.show)
        self.game.show()

    def game_over(self, name, score):
        self.high_scores.append((score, name))
        self.high_scores = sorted(self.high_scores, reverse=True)[:10]
        self.high_score.show(self.high_scores)


if __name__ == "__main__":
    MainWindow().mainloop()
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Updating records 1 to n on an SQLite table KevinBrown 2 2,657 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