Reputation: 143
I googled a lot but it didn't work. Posted a question last week but no answer as it seems that it was too lengthily...
Hopefully, the new question is much clearer.
This is just a small piece of the code and if you run it you will be able to reproduce the issue. What I need to do basically is to get user input (E1 from mainGUI class) and pass it to insert() function from Database class. The error I get when I try to add an entry is:
"self.curs.execute("INSERT INTO diary VALUES (?)", (date)) sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 0 supplied."
I can read from the database with no problems.
Any help would be much appreciated.
from tkinter import *
import sqlite3
class mainGUI(object):
def __init__(self,window):
self.window=window
self.E1 = Entry(window)
self.E1.grid(row=1, column=0)
self.EG1 = self.E1.get()
global E4
E4 = Listbox(window)
E4.grid(row=2)
B1 = Button(window, text="Add entry", command=lambda: database.insert(self.EG1))
B1.grid(row=1, column=4)
B2 = Button(window, text="View all", command=database.view_all)
B2.grid(row=2, column=4, sticky="WN")
window.mainloop()
class Database(mainGUI):
def __init__(self, db):
self.conn = sqlite3.connect(db)
self.curs = self.conn.cursor()
self.curs.execute("CREATE TABLE IF NOT EXISTS diary (date TEXT)")
self.conn.commit()
def insert(self,date):
database.add_entry(date)
E4.delete(0, END)
E4.insert(END,(date))
def add_entry(self,date):
self.curs.execute("INSERT INTO diary VALUES (?)", (date))
self.conn.commit()
def view_all(self):
E4.delete(0, END)
self.curs.execute("SELECT * FROM diary")
data = self.curs.fetchall()
for row in data:
E4.insert(END,row)
if __name__ == "__main__":
database = Database("dbase.db")
window=Tk()
gui = mainGUI(window)
Upvotes: 2
Views: 2492
Reputation: 385970
If you are using classes, you should not be using global variables. Instead, you need to be accessing attributes and methods of your object instances. That means creating E4
as an instance variable, and access it via the instance of the GUI class.
Also, your Database should not inherit from mainGUI
. That is not how inheritance should be used.
You have your Database coded so that it need to alter the GUI, which is unusual. Instead, your GUI should be the only thing that can modify the GUI, and your Database should be the only thing that modifies the database. When the GUI needs to send information to, or get information from the database, it can call methods on the database.
So, the first step is to pass the database object to your mainGUI
class (which should be named MainGUI
according to PEP8):
class MainGUI(object):
def __init__(self,window, db):
self.window = window
self.db = db
...
Next, pass in the database object when you create the GUI:
if __name__ == "__main__":
database = Database("dbase.db")
window=Tk()
gui = MainGUI(window, database)
With that, you can now use the database to get and fetch data, and use the GUI to display the data.
For example, your GUI should have the "view_all" method, since it deals with altering the view. It should call the "get_all" method of the database. By not using lambda
, your code becomes much easier to read, write, and debug.
class mainGUI(object):
def __init__(self,window, db):
...
self.E4 = Listbox(...)
...
B2 = Button(..., command=self.view_all)
def view_all(self):
data = self.db.get_all()
self.E4.delete(0, END)
for row in data:
self.E4.insert(END,row)
Finally, create a get_all
method in your Database
that does nothing but get and return the data:
class MainGUI(object):
def get_all(self):
self.curs.execute("SELECT * FROM diary")
data = self.curs.fetchall()
return data
With all of the above, and after applying the same concepts to the other methods (ie: the Database
class should only set or get data), you have a reusable Database
class that is completely independent of the GUI that uses it.
Upvotes: 2
Reputation: 1932
One thing I noticed is you did not associate any textvariable
to the Entry widget, hence it is passing null value to the other class. Please try making self.EG1
a textvariable
and then passing it to the function.
self.EG1 = StringVar()
self.E1 = Entry(window,textvariable=self.EG1)
self.E1.grid(row=1, column=0)
B1 = Button(window, text="Add entry", command=lambda: database.insert(self.EG1.get()))
Upvotes: 0