Python Tkinter row delete function only works once

Question:

Below is the code for a smaller version of a project I am working on. Basically when I try to delete one of the entries, the delete function works, but only once. After that it starts duplicating the entries I have deleted until giving me the IndexError: list assignment index out of range

from tkinter import *
gui = Tk()
details_list = []
counters = {'total_entires':0, 'entries_count':0}
error_print = Label(gui)

name_entry = Entry(gui)
name_entry.grid(column=1, row=0, sticky=W)

delete_row_entry = Entry(gui, width=5)
delete_row_entry.grid(column=4,row=3, sticky=W, pady=(2,0))

def print_entries():
    global details_list, row_display, name_display
    line_no = ""
    for x in range(len(details_list)):
        line_no = str(x + 1)
        row_display = Label(gui, text=line_no)
        row_display.grid(column=0, row=x+2)

        name_display = Label(gui, text=(details_list[x][0]))
        name_display.grid(column=1, row=x+2)

def delete_row():
    global details_list, row_display
    del details_list[int(delete_row_entry.get()) - 1]
    entries_count = counters['entries_count']
    counters['total_entires'] -= 1
    delete_row_entry.delete(0,'end')
    row_display.destroy()
    name_display.destroy()
    print_entries()

def append_name():
    details_list.append([name_entry.get()])
    counters['total_entires'] += 1

def labels():
    Label(gui, text='Row').grid(column=0, row=1, sticky=W, padx=(0,5))
    Label(gui, text='Name').grid(column=1, row=1, sticky=W, padx=5)


def buttons():
    Button(gui, text='Quit', command=quit, width=15).grid(column=4, row=0, sticky=W)
    Button(gui, text='Append Details', command=append_name, width=15).grid(column=4, row=1, 
    sticky=W)
    Button(gui, text='Print Details', command=print_entries, width=15).grid(column=4, row=2, 
    sticky=W)
    Button(gui, text='Delete Row', command=delete_row, width=10).grid(column=4, row=3, 
    sticky=E)



def main():
    labels()
    buttons()
    gui.mainloop()
main()
Asked By: haoisdfoas

||

Answers:

There are two issues in your code:

  • you have created new set of labels whenever print_entries() is executed
  • the two .destroy() lines just destroy the labels in the last row of the set of labels created inside print_entries()

To fix the issues:

  • create a list to store those labels created inside print_entries()
  • delete existing labels before populating new labels inside print_entries()

Below are the modified print_entries() and delete_row() functions:

...
# create a list to store those labels
label_list = []

def print_entries():
    # clear current table
    for w in label_list:
        w.destroy()
    label_list.clear()

    # show the new table
    for x in range(len(details_list)):
        row_display = Label(gui, text=x+1)
        row_display.grid(column=0, row=x+2)

        name_display = Label(gui, text=details_list[x][0])
        name_display.grid(column=1, row=x+2)
        # store the labels in the list
        label_list.extend([row_display, name_display])

def delete_row():
    try:
        size = len(details_list)
        idx = int(delete_row_entry.get()) - 1  # may raise exception
        if size and 0 <= idx < size:
            del details_list[idx]
            # below line seems useless
            #entries_count = counters['entries_count']
            counters['total_entires'] -= 1
            delete_row_entry.delete(0, 'end')
            print_entries()
        else:
            print('row number is out of range' if size else 'empty list')
    except ValueError as ex:
        print(ex)
...
Answered By: acw1668
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.