Why I continue getting the error :
missing 1 required positional argument: 'category_id'
when the argument is already passed within query function in Backend
class? I also don't understand the error of unfilled self
or missing positional argument self
:
missing 1 required positional argument: 'self'
I tried passing self
to display_account_types()
in Frontend
class but it doesn't reflect. Do I need to pass self
within the inner nested functions within a class?
import tkinter
from tkinter import *
from tkinter import ttk
import tkinter.messagebox
import sqlite3
root =Tk()
root.title('Simple Application')
root.config(bg='SlateGrey')
root.geometry("")
# BackEnd
class Backend():
def __init__(self):
self.conn = sqlite3.connect('accounting.db')
self.cur = self.conn.cursor()
self.conn.execute("""CREATE TABLE IF NOT EXISTS account_type(
id INTEGER PRIMARY KEY,
category_type INTEGER NOT NULL,
category_id TEXT NOT NULL
)"""),
self.conn.commit()
self.conn.close()
def insert_account_type(self, category_type, category_id):
self.conn = sqlite3.connect('accounting.db')
self.cur = self.conn.cursor()
self.cur.execute("""INSERT INTO account_type(category_id, category_type) VALUES(?,?);""",
(self,category_type, category_id,))
self.conn.commit()
self.conn.close()
def view_account_type(self):
self.conn = sqlite3.connect('accounting.db')
self.cur = self.conn.cursor()
self.cur.execute("SELECT * FROM account_type")
self.rows = self.cur.fetchall()
self.conn.close()
return self.rows
# calling the class
tb = Backend()
# Front End
class Frontend():
def __init__(self, master):
# Frames
self.top_frame = LabelFrame(master,bg ='SlateGrey', relief=SUNKEN)
self.top_frame.pack()
self.bottom_frame = LabelFrame(master, bg = 'SlateGrey', relief=SUNKEN)
self.bottom_frame.pack()
self.right_frame = LabelFrame(self.top_frame, bg = 'SlateGrey', relief = FLAT,
text = 'Details Entry',fg = 'maroon')
self.right_frame.pack(side = RIGHT, anchor = NE)
self.side_frame = LabelFrame(self.top_frame,bg ='SlateGrey',relief=SUNKEN,text = 'Menu Buttons',fg = 'maroon')
self.side_frame.pack(side = LEFT,anchor = NW)
self.bot_frame = LabelFrame(self.bottom_frame, bg='Grey',relief = SUNKEN,text = 'Field View',fg = 'maroon')
self.bot_frame.pack(side = BOTTOM,anchor = SW)
# Side Buttons
self.btn1 = Button(self.side_frame,
text='Main Account Types',
bg='SteelBlue4',
font=('cambria', 11),
anchor=W,
fg='white',
width=18,height=2,
command=lambda :[self.main_account()])
self.btn1.grid(row=0, column=0, pady=0, sticky=W)
def main_account(self):
# variables
self.category_type = StringVar()
self.category_id = StringVar()
# functions
def add_main_accounts():
if self.category_type.get() == "" or self.category_id.get() == "":
tkinter.messagebox.showinfo('All fields are required')
else:
Backend.insert_account_type(
self.category_type.get(),
self.category_id.get(),) # category type unfilled
tkinter.messagebox.showinfo('Entry successful')
def display_account_types(self):
self.trv.delete(*self.trv.get_children())
for self.rows in Backend.view_account_type(self):
self.trv.insert("", END, values=self.rows)
def get_account_type(e):
self.selected_row = self.trv.focus()
self.data = self.trv.item(self.selected_row)
global row
row = self.data["values"]
"""Grab items and send them to entry fields"""
self.category_id.set(row[1])
self.category_type.set(row[2])
"""=================TreeView==============="""
# Scrollbars
ttk.Style().configure("Treeview", background = "SlateGrey", foreground = "white", fieldbackground = "grey")
scroll_x = Scrollbar(self.bot_frame, orient = HORIZONTAL)
scroll_x.pack(side = BOTTOM, fill = X)
scroll_y = Scrollbar(self.bot_frame, orient = VERTICAL)
scroll_y.pack(side = RIGHT, fill = Y)
# Treeview columns & setting scrollbars
self.trv = ttk.Treeview(self.bot_frame, height=3, columns=
('id', 'category_id', 'category_type'), xscrollcommand = scroll_x.set, yscrollcommand = scroll_y.set)
# Treeview style configuration
ttk.Style().configure("Treeview", background = "SlateGrey", foreground = "white", fieldbackground = "grey")
# Configure vertical and Horizontal scroll
scroll_x.config(command = self.trv.xview)
scroll_y.config(command = self.trv.yview)
# Treeview Headings/columns
self.trv.heading('id', text = "No.")
self.trv.heading('category_id', text = 'Category ID')
self.trv.heading('category_type', text = 'Category Type')
self.trv['show'] = 'headings'
# Treeview columns width
self.trv.column('id', width = 23)
self.trv.column('category_id', width = 70)
self.trv.column('category_type', width = 100)
self.trv.pack(fill = BOTH, expand = YES)
# Binding Treeview with data
self.trv.bind('<ButtonRelease-1>',get_account_type)
# Account Types Labels
self.lbl1 = Label(self.right_frame,text = 'Category ID',anchor = W,
width=10,font = ('cambria',11,),bg = 'SlateGrey')
self.lbl1.grid(row = 0,column = 0,pady = 5)
self.lbl2 = Label(self.right_frame, text = 'Category Type', anchor = W,
width = 10,font = ('cambria',11,),bg = 'SlateGrey')
self.lbl2.grid(row = 1, column = 0,pady = 5,padx=5)
self.blank_label = Label(self.right_frame, bg='SlateGrey')
self.blank_label.grid(row=2, columnspan=2, pady=10)
# Account Type Entries
self.entry1 = Entry(self.right_frame,textvariable = self.category_id,
font = ('cambria',11,),bg = 'Grey',width=14)
self.entry1.grid(row = 0,column=1,sticky = W,padx = 5)
self.entry2 = Entry(self.right_frame, textvariable = self.category_type,
font = ('cambria', 11,), bg = 'Grey',width = 14)
self.entry2.grid(row = 1, column = 1, sticky = W,pady = 5,padx = 5)
# Buttons
self.btn_1 = Button(self.right_frame,text = 'Add',font = ('cambria',12,'bold'),bg = 'SlateGrey',
activebackground='green', fg = 'white',width=12,height = 2,relief=RIDGE,
command = lambda :[add_main_accounts()])
self.btn_1.grid(row = 3,column = 0,pady = 15)
self.btn_2 = Button(self.right_frame, text = 'View', font = ('cambria', 12, 'bold'),
bg = 'SlateGrey',command=lambda :[display_account_types()],
activebackground='green', fg ='white', width=12, height = 2, relief = RIDGE)
self.btn_2.grid(row = 3, column = 1)
# calling the class
app = Frontend(root)
root.mainloop()
I got and answer to this question,
I just passed in the 'self' argument to the inner nested functions of the class as below and it worked.
# functions
def add_main_accounts(self):
if self.category_id.get() == "" or self.category_type.get() == "":
tkinter.messagebox.showinfo('All fields are required')
else:
Backend.insert_account_type(self,
self.category_id.get(),
self.category_type.get()) # category type unfilled
tkinter.messagebox.showinfo('Entry successful')
def display_account_types(self):
self.trv.delete(*self.trv.get_children())
for rows in Backend.view_account_type(self):
self.trv.insert("", END, values = rows)
return
def get_account_type(e):
self.selected_row = self.trv.focus()
self.data = self.trv.item(self.selected_row)
global row
self.row = self.data["values"]
"""Grab items and send them to entry fields"""
self.category_id.set(row[1])
self.category_type.set(row[2])