0

Im trying to get this Listbox in tkinter to update from a sqlite3 database when a button is clicked. I actually had it working using root.after(1000, function) method but the cursor kept resetting every time it was updated.

At the moment I can't get the listbox to populate at the button click.

I would love any help. Thanks!

root=Tk()
ListBox1 = Listbox(root)
ListBox1.grid(row=0, column=0 , sticky='nsew')

def ListUpdate():
    listlist = []

#populates list from sql database in a for loop

    return listlist

def ListPopulate(listlist):
    ListBox1.delete(0, END)
    for i in range(0,len(listlist[i]):
        ListBox1.insert(END, listlist[i])

ButtonUpdate = Button(root, text='Update', command=ListPopulate(listlist))
ButtonUpdate.grid(row=5, column=6, sticky='nsew')

2 Answers2

2

You're using command wrong. Replace:

Button(..., command=ListPopulate(listlist))

with:

Button(..., command=lambda l=ListUpdate(): ListPopulate(l))
Nae
  • 14,209
  • 7
  • 52
  • 79
1

Your command= argument for your Button calls ListPopulate(listlist) when the button is created and assigns its result (which is None, since you don't return anything from that function) as the command. You have therefore told the Button object that it has no command.

You're naturally going to run into problems passing the list to all the places it needs to go in an event-driven system. One approach is to make the list ListList a global variable. Define it outside all your functions at the top of the script, with your other variables:

ListBox1 = Listbox(root)
ListBox1.grid(row=0, column=0 , sticky='nsew')
listlist = []

Next, change the first line of ListUpdate() to use a slice assignment to empty out the existing list object, so you don't need to declare the object global in that function.

def ListUpdate():
    listlist[:] = []

Then change ListPopulate() to take no arguments, since it's going to use the global listlist.

def ListPopulate():

Finally, write your Button() constructor to pass ListPopulate rather than calling it.

ButtonUpdate = Button(root, text='Update', command=ListPopulate)

Globals are generally bad practice. What you probably should do is subclass Listbox and give it an attribute that holds the list. Then your two functions would be methods of that class. (In fact, you probably want to update the displayed list on screen every time you change its contents... so you should have one method, not two.) I'll leave that as an exercise for when you learn object-oriented programming.

kindall
  • 178,883
  • 35
  • 278
  • 309
  • Thanks!! This helps a lot. It works, I can tell because the cursor resets to the top when I click 'Update', however when I add new data to the database, it doesn't update the list. I put in a root.after(1000, ListUpdate) and a print(listlist) above it, in the console it just prints the once. Is there something obvious I'm missing? – Talvinder Bains Mar 03 '18 at 18:13