Short description: I made home window where I'm entering TopLevel
window where buttons are created in loop with data from database, let's say that 4 buttons are created and names 1,2,3,&4 for example.
So when you click on one of those buttons there will be some kind of counter like 0/4, there is button "Plati odabrano" when you press it will add 1/4 and on.. after it hit 4/4 button is deleted and it works fine, but when I exit TopLevel
window and enter in again from home window, button that was beside that button we deleted took deleted button spot and stayed also on it's last spot, so I still got 4 buttons but they are now named 1,2,4,&4.
So I recreated code in simpler version and it works just fine without that bug, but I can't find bug in my main code to fix it. Here I will paste both codes and if someone can test it in their interpreter and check for bug I would be so grateful.
Here is my main code:
from tkinter import *
import sqlite3
conn = sqlite3.connect('Financije.db')
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS PRIMANJA
([ID] INTEGER PRIMARY KEY,[Opis] text, [Iznos] integer, [Datum] text)''')
c.execute('''CREATE TABLE IF NOT EXISTS OTPLATA_NA_RATE
([ID] INTEGER PRIMARY KEY,[Opis] text, [Iznos_rate] integer, [Broj_rata] text, [Datum_kupnje] text)''')
c.execute('''CREATE TABLE IF NOT EXISTS SKIDANJE_S_RAČUNA
([ID] INTEGER PRIMARY KEY,[Opis] text, [Iznos] integer, [Date] text)''')
c.execute('''CREATE TABLE IF NOT EXISTS KASICA
([ID] INTEGER PRIMARY KEY, [Stanje_računa] integer)''')
c.execute('SELECT * FROM KASICA')
check = c.fetchone()
if check is None:
c.execute('INSERT INTO KASICA VALUES (?, ?);', (None, 0.0))
c.execute('SELECT * FROM OTPLATA_NA_RATE')
check = c.fetchone()
if check is None:
c.execute('INSERT INTO OTPLATA_NA_RATE VALUES (?, ?, ?, ?, ?);', (None, "Test1", 600, "0/2", "12/08/2021"))
c.execute('INSERT INTO OTPLATA_NA_RATE VALUES (?, ?, ?, ?, ?);', (None, "Test2", 600, "0/3", "12/08/2021"))
c.execute('INSERT INTO OTPLATA_NA_RATE VALUES (?, ?, ?, ?, ?);', (None, "Test3", 600, "0/4", "12/08/2021"))
c.execute('INSERT INTO OTPLATA_NA_RATE VALUES (?, ?, ?, ?, ?);', (None, "Test4", 600, "0/5", "12/08/2021"))
c.execute('INSERT INTO OTPLATA_NA_RATE VALUES (?, ?, ?, ?, ?);', (None, "Test5", 600, "0/6", "12/08/2021"))
# Save (commit) the changes
conn.commit()
class FinancialCalc:
def __init__(self, master):
self.lista_opisa_rata = list()
self.dict_for_buttons = dict()
# Start screen define:
self.master = master
self.master.title("Test")
self.master.geometry("300x300")
self.master.resizable(False, False)
self.otplata_na_rate_button = Button(master, text="payment in installments",
command=self.otplata_na_rate_deiconify)
self.otplata_na_rate_button.place(x=95, y=155)
# Otplata_na_rate TopLevel - definiranje
self.onr_top = Toplevel()
self.onr_top.withdraw()
self.onr_top.protocol("WM_DELETE_WINDOW", lambda: (self.master.deiconify(), self.onr_top.withdraw()))
self.onr_top.title("Test")
self.onr_label = Label(self.onr_top, text="List of payments:", font=("Helvetica", 11, "underline", "bold"))
self.onr_opis_label = Label(self.onr_top, text="Payment description:", font=("Helvetica", 11, "underline", "bold"))
self.onr_oznacena_rata_label = Label(self.onr_top, text="Installment description:", font=("Helvetica", 11))
self.onr_broj_rata_label = Label(self.onr_top, text="Installments:", font=("Helvetica", 11))
self.onr_iznos_rate_label = Label(self.onr_top, text="Value:", font=("Helvetica", 11))
self.onr_datum_isplate_label = Label(self.onr_top, text="Final payment:", font=("Helvetica", 11))
self.onr_oznacena_rata_txt = Label(self.onr_top, text="", font=("Helvetica", 11))
self.onr_broj_rata_txt = Label(self.onr_top, text="", font=("Helvetica", 11))
self.onr_iznos_rate_txt = Label(self.onr_top, text="", font=("Helvetica", 11))
self.onr_datum_isplate_txt = Label(self.onr_top, text="", font=("Helvetica", 11))
self.onr_pl_pojed_btn = Button(self.onr_top, text="Pay selected", command=self.pay_selected)
def pay_selected(self):
p_description = self.onr_oznacena_rata_txt.cget("text")
num_of_installments = self.onr_broj_rata_txt.cget("text").split("/")
if int(num_of_installments[0])+1 >= int(num_of_installments[1]):
c.execute('DELETE FROM OTPLATA_NA_RATE WHERE Opis = ?', (p_description,))
conn.commit()
btn_to_del = self.dict_for_buttons[p_description]
btn_to_del.destroy()
self.dict_for_buttons.pop(p_description)
self.lista_opisa_rata.clear()
else:
target_3_novo = str(int(num_of_installments[0])+1) + "/" + num_of_installments[1]
c.execute('UPDATE OTPLATA_NA_RATE SET Broj_rata = ? WHERE Opis = ?', (target_3_novo, p_description,))
conn.commit()
self.get_description(p_description)
def get_description(self, opis):
c.execute('SELECT * FROM OTPLATA_NA_RATE WHERE Opis=?;', (opis,))
for x in c:
dodaj_godinu = 0
self.onr_oznacena_rata_txt.config(text=x[1])
self.onr_iznos_rate_txt.config(text=str(x[2]) + " kn")
self.onr_broj_rata_txt.config(text=x[3])
datum_racunanje = int(x[4].split("/")[1]) + int(x[3].split("/")[1])
while datum_racunanje > 12:
datum_racunanje -= 12
dodaj_godinu += 1
datum_isplate = str(datum_racunanje) + "/" + str(int(x[4].split("/")[2])+dodaj_godinu)
self.onr_datum_isplate_txt.config(text=datum_isplate)
def otplata_na_rate_deiconify(self):
# Otplata_na_rate TopLevel - define window:
self.master.withdraw()
self.onr_top.deiconify()
self.onr_label.grid(row=0, columnspan=3, sticky="NESW")
self.onr_opis_label.grid(row=0, column=5, sticky="NESW")
self.onr_oznacena_rata_label.grid(row=1, column=4, padx=5, sticky="E")
self.onr_broj_rata_label.grid(row=2, column=4, padx=5, sticky="E")
self.onr_iznos_rate_label.grid(row=3, column=4, padx=5, sticky="E")
self.onr_datum_isplate_label.grid(row=4, column=4, padx=5, sticky="E")
self.onr_oznacena_rata_txt.grid(row=1, column=5, padx=5, sticky="NSWE")
self.onr_broj_rata_txt.grid(row=2, column=5, padx=5, sticky="NSWE")
self.onr_iznos_rate_txt.grid(row=3, column=5, padx=5, sticky="NSWE")
self.onr_datum_isplate_txt.grid(row=4, column=5, padx=5, sticky="NSWE")
c.execute('SELECT Opis FROM OTPLATA_NA_RATE')
for opis in c:
self.lista_opisa_rata.append(opis[0])
column = 0
row = 1
for opis in self.lista_opisa_rata:
# Append function to button
function = lambda x=opis: self.get_description(x)
rata_button = Button(self.onr_top, text=opis, width=10, command=function)
rata_button.grid(row=row, column=column, padx=5, pady=5)
self.dict_for_buttons[opis] = rata_button
column += 1
if column == 3:
row += 1
column = 0
# Define placement of Button widget - created with loop
if row < 5:
row = 5
if row >= 5:
row += 1
self.onr_pl_pojed_btn.grid(row=row, column=5, padx=2, pady=5)
x = self.master.winfo_x()
y = self.master.winfo_y()
self.onr_top.geometry(f"+{x}+{y}")
root = Tk()
my_gui = FinancialCalc(root)
root.mainloop()
and this is code that I recreated so you guys can understand what I'm trying to do:
from tkinter import *
root = Tk()
toplvl = Toplevel()
toplvl.withdraw()
toplvl.protocol("WM_DELETE_WINDOW", lambda: (root.deiconify(), toplvl.withdraw()))
button_id = dict()
def btn_destroy():
picked_btn = str(lbl_picked_btn.cget("text").split(":")[1]).rstrip()
if picked_btn != "":
txt = int(lbl.cget("text").split("/")[0]) + 1
lbl.config(text=str(txt) + "/3")
if txt == 3:
btn_to_del = button_id[int(picked_btn)]
btn_to_del.destroy()
lbl.config(text="0/3")
def btn_pick(x):
lbl_picked_btn.config(text="Button picked:"+str(x))
lbl_desc = Label(toplvl, text="Pick button and click Destroy 3 times to destroy it", font=("Helvetica", 11))
lbl_desc.grid(row=0, columnspan=4)
lbl_picked_btn = Label(toplvl, text="Button picked:", font=("Helvetica", 11))
lbl_picked_btn.grid(row=1, column=1, columnspan=2)
btn_d = Button(toplvl, width=10, text="Destroy", command=btn_destroy)
btn_d.grid(row=1, column=0)
lbl = Label(toplvl, text="0/3", font=("Helvetica", 11))
lbl.grid(row=1, column=3)
row = 2
column = 0
for i in range(5):
function = lambda x=i: btn_pick(x)
btn = Button(toplvl, width=10, text=str(i), command=function)
btn.grid(row=row, column=column)
button_id[i] = btn
column += 1
def top():
root.withdraw()
toplvl.deiconify()
start_btn = Button(root, text="Start", command=top)
start_btn.pack()
root.mainloop()
Here are pictures of bug:
1st pic is how it looks before deleteing
Second pic is how window looks like when button is deleted but still didn't leave and enter TopLevel
Last pic is how window looks like and you can see that part about button
Sorry for this long post and a lot of information, but I just want to explain everything :)