Home > Enterprise >  _tkinter.TclError: bad listbox index "0 1 2"
_tkinter.TclError: bad listbox index "0 1 2"

Time:08-18

I have a listBox in tkinter and 2 buttons. One of them delete the selected items in ListBox. If I select every items and y try delete them I get the follow error:

_tkinter.TclError: bad listbox index "0 1 2": must be active, anchor, end, @x,y, or a number

I don't find how I can to solve it.

This is my code:

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
root.title("Listas en tkinter")

root.columnconfigure(0, weight=4)
root.rowconfigure(0, weight=4)

def AgregarItem(event):
    # Obtener elementos del listbox
    elementos = lstProductos.get(0, tk.END)
    # Combprobar si nuevo elemento existe en listbox
    if item.get() in elementos:
        tk.messagebox.showinfo(message="El elemento ya existe en la lista",
                               title="Error")
    else:
        lstProductos.insert(tk.END, item.get())
    
    txtProducto.delete(0, "end")

def EliminarItem(event):
    elementos = lstProductos.get(0, tk.END)
    if elementos != (): 
        lstProductos.delete(lstProductos.curselection())

# Titulo
lblTitulo = ttk.Label(root, text="Lista de la compra")
lblTitulo.configure(font=("Arial", 24, 'bold'))
lblTitulo.grid(column=0, row=0, columnspan=4, padx=5, pady=5)

# Lista
lstProductos = tk.Listbox(root)
lstProductos.grid(column=0, row=1, rowspan=3, pady=5)
lstProductos.configure(selectmode="multiple")

# Scrollbar de la lista
scrollbar = ttk.Scrollbar(root, orient="vertical", command=lstProductos.yview)
scrollbar.grid(column=1, row=1, rowspan=3, sticky=tk.NS, pady=5)
lstProductos['yscrollcommand'] = scrollbar.set

# Etiqueta con instrucciones
lblInstrucciones = ttk.Label(root, text="Agregar: Introduce el nombre\ndel producto y pulsa Agregar\n\nEliminar: Selecciona producto\ny pulsa Eliminar")
lblInstrucciones.grid(column=2, row=1, columnspan=2, padx=5, pady=5)

# Cuadro de texto
item=tk.StringVar()
txtProducto = ttk.Entry(root, textvariable=item)
txtProducto.grid(column=2, row=2, columnspan=2, padx=5, pady=5)


# Boton agregar 
botAgregar = tk.Button(root, text="Agregar item" )
botAgregar.grid(column=2, row=3)
botAgregar.bind('<Button-1>', AgregarItem)

# Boton eliminar
botEliminar = tk.Button(root, text="Eliminar item" )
botEliminar.grid(column=3, row=3)
botEliminar.bind('<Button-1>', EliminarItem)

root.mainloop()

Thanks

CodePudding user response:

The right way to delete a set of items in a listbox is by getting the list of selected indexes and then looping through it and then individually deleting them.

But there is a problem in that, if you delete the first selected index then you will notice the index positions of other elements below the deleted item now change too and hence deleting will not be proper. So you will have to delete from the bottom so the previous items do not get reindexed after deletion:

def EliminarItem(event):
    elementos = lstProductos.get(0, tk.END)
    items = lstProductos.curselection()

    if elementos: # Same as `if elemntos != ()`
        for i in items[::-1]: # items[::-1] will reverse the list
            lstProductos.delete(i)

Note that you are using bind with the buttons, which is absolutely unnecessary. You should really be using command option of button, which will trigger the function when button is pressed.

# Boton agregar 
botAgregar = tk.Button(root, text="Agregar item", command=AgregarItem)
botAgregar.grid(column=2, row=3)

... and don't forget to remove event as a parameter in the functions as you are no longer passing it in.

  • Related