astrodavis77 astrodavis77 - 24 days ago 20
Python Question

Transferring user input from Tkinter widget into SQLite database

I'm a new Python user (v3.5) trying to work with Tkinter and SQLite. I'm having an issue getting user input from widgets (combo and spinboxes) into variables and then feeding those variables into the SQLite database. I've tried to diagnose the problem myself and I believe the issue is getting the data from the widget into the variable. I've tinkered with the code and searched around online for solutions but I haven't been able to get anything to work yet. The relevant code is below. I've tried to hack out the irrelevant bits for brevity.

from tkinter import *
from tkinter.ttk import *
import sqlite3

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


class GUI:
def __init__(self):
self.root = Tk()
self.player_selection_and_score()
self.process_button()
self.create_table()

def player_selection_and_score(self):
player = StringVar
top = LabelFrame(self.root)
top.grid(column=0, row=0)


player1_selection = Combobox(top, width=10, textvariable=player, state='readonly')
player1_selection["values"] = ("Player1", "Player2", "Player3")
player1_selection.grid(column=1, row=0, sticky="w")
player1_selection.current(0)
player1_selection.bind("<<ComboboxSelected>>")
global player1_var
player1_var = player1_selection.get()

player1_score_entry = Spinbox(top, width=5, from_=0, to=10)
player1_score_entry.grid(column=4, row=0)
player1_score_entry.bind("<<SpinboxSelected>>")
global player1_score_var
player1_score_var = player1_score_entry.get()

def process_button(self):
bottom = LabelFrame(self.root)
bottom.grid(column=0, row=2)

process_button = Button(bottom, text="Process Result", command=self.data_entry)
process_button.pack()

def create_table(self):
c.execute("CREATE TABLE IF NOT EXISTS fixtures (player1 TEXT, player1_score REAL)")

def data_entry(self):
c.execute("INSERT INTO fixtures (player1, player1_score) VALUES (?, ?, ?, ?)", (player1_var, player1_score_var))
conn.commit()

player1_var = GUI()
player1_score_var = GUI()

# Start GUI
gui = GUI()
gui.root.mainloop()

conn.close()
c.close()


I'm pretty sure the issue is with these specific lines of code:

player1_selection.bind("<<ComboboxSelected>>")
global player1_var
player1_var = player1_selection.get()


player1_score_entry.bind("<<SpinboxSelected>>")
global player1_score_var
player1_score_var = player1_score_entry.get()


Thank you!!

Answer

In your code you get value from Combobox and Spinbox at start, not when they change value.

Normally you have to bind functions to "<<ComboboxSelected>>" and command= in Spinbox which will use get() to get selected values.

But you don't need it because you can get value when you press button.

See more in comments.

I keep bind("<<ComboboxSelected>>", self.on_combobox_select) and Spinbox(... , command=self.on_spinbox_select) but you don't need it.

import tkinter as tk
import tkinter.ttk as ttk
import sqlite3

class GUI:

    def __init__(self):
        self.root = tk.Tk()
        self.player_selection_and_score()
        self.process_button()
        self.create_table()

    def player_selection_and_score(self):
        #self.player = StringVar() # forgot (), use `self`
        top = tk.LabelFrame(self.root)
        top.grid(column=0, row=0)

        self.player1_selection = ttk.Combobox(top, width=10, state='readonly') # , textvariable=player
        self.player1_selection["values"] = ("Player1", "Player2", "Player3")
        self.player1_selection.grid(column=1, row=0, sticky="w")
        self.player1_selection.current(0)

        self.player1_selection.bind("<<ComboboxSelected>>", self.on_combobox_select)

        #global player1_var # better use `self.`
        #player1_var = player1_selection.get() # useless

        self.player1_score_entry = tk.Spinbox(top, width=5, from_=0, to=10, command=self.on_spinbox_select)
        self.player1_score_entry.grid(column=4, row=0)

        #global player1_score_var # better use `self.`
        #player1_score_var = player1_score_entry.get() # useless

    def on_combobox_select(self, event):
        print("Combobox:", event.widget.get())

    def on_spinbox_select(self):
        print("Spinbox:", self.player1_score_entry.get())

    def process_button(self):
        bottom = tk.LabelFrame(self.root)
        bottom.grid(column=0, row=2)

        process_button = tk.Button(bottom, text="Process Result", command=self.data_entry)
        process_button.pack()

    def create_table(self):
        c.execute("CREATE TABLE IF NOT EXISTS fixtures (player1 TEXT, player1_score REAL)")

    def data_entry(self):
        player1_var = self.player1_selection.get()
        player1_score_var = self.player1_score_entry.get()

        # too many `?`
        c.execute("INSERT INTO fixtures (player1, player1_score) VALUES (?, ?)", (player1_var, player1_score_var))
        conn.commit()

#player1_var = GUI() # ??? something stupid
#player1_score_var = GUI() # ??? something stupid

# --- main ---

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

gui = GUI()
gui.root.mainloop()

c.close() # first close `c` later `conn`
conn.close()