'python tkinter append list

I am an amateur python programer with 2 months of experience. I am trying to write a GUI to-do list through tkinter. The actual placement of the buttons are not important. I can play around with those after. I need some help with displaying the appended item to the list. In the program, it updates well on the digit, but it won't print onto the list. I double checked it on the console and it says "tkinter.StringVar object at 0x102fa4048" but didn't update the actual list. What I need help is how can I update the list Main_Q on my the label column? Much appreciate some direction and coding help. Thanks.

Main_Q =["read","clean dishes", "wash car"]


from tkinter import*
root=Tk(className="total tasks in the Q")


#formula

def update():
global Main_Q
a=len(Main_Q)
num.set(a)

def add2list():
Main_Q.append(name)
a=len(Main_Q)
num.set(a)
print (Main_Q)


#output

num=StringVar()
y=Label(root, textvariable=num).grid(row=0, column=1)

#input

name=StringVar()
b=Entry(root, textvariable=name).grid(row=7,column=0)


#buttons
z=Button(root, text="update", command=update).grid(row=7, column=2)
add2list=Button(root,text="add", command=add2list).grid(row=7,         
column=1)


r = 0
for c in Main_Q:
Label(text=c, relief=RIDGE,width=15).grid(row=r,column=0)
r = r + 1

root.mainloop()


Solution 1:[1]

Your problem is that your for loop which build up your labels doesnt get called after each time you have entered a new "task". To easily fix this you can move this loop into your update function.

If you want to prevent of looping through widget everytime you can create a new list with all widgets which already have been created:

createdWidgets = []
widgetsQueue = []

In your update function you than have to iterate through the widgetsQueue (widgetsQueue.pop() for instance), create the widgets and append the widget to the createdWidgetes list.

def update():
    global Main_Q
    r = 0
    for c in Main_Q:
        Label(text=c, relief=RIDGE,width=15).grid(row=r,column=0)
        r += 1 # shorthand for r = r + 1

Some addition notes:

  1. for the entry it is easier to seperate the definition and placement:

    b = Entry(root)
    b.grid(row=7,column=0)
    

    because than Entry() returns its instance and you can use it to get the text:

    b.get()
    
  2. if you go shopping do you throw everything into one bag ?

    from tkinter import *
    

    does axactly that(in this case the globals() variable would be the bag).If you want to read more about that Importing Python Modules. To prevent that and shorten the amount of letters to type:

    import tkinter as t # or tk 
    root = t.Tk()
    

*But for sure, if you just want a small program its okay.

Solution 2:[2]

Design:

To resolve your problem, you need to design this simple solution:

  1. retrieve the text of the Tkinter.Entry widget using get() method.
  2. add the text you got in 1 to Main_Q using append() method.
  3. bind the button that updates on click both Main_Q and your GUI using command method.
  4. create a new Tkinter.Label widget, set its text to the value you got in 1 and increment its corresponding row in the GUI.

I prefer to organize your code within a class that contains a constructor where Main_Q is initialized so that we call initialize_user_interface() to initialize the GUI with its three elements:

    def __init__(self, parent):
            Tkinter.Frame.__init__(self, parent)
            self.parent = parent
            self.Main_Q = ["read", "clean dishes", "wash car"]
            self.r = 0 # position of the row of each label
            self.initialize_user_interface()

The method initialize_user_interface() does what its name says. We mainly bind the function update_gui() that inserts a new label with the text set to what the user types in Tkinter.Entry widget using command = self.update_gui

ef initialize_user_interface(self):
        self.parent.title("Update GUI")
        self.parent.grid_rowconfigure(0, weight = 1)
        self.parent.grid_columnconfigure(0, weight = 1)

        for e in self.Main_Q:
            Tkinter.Label(self.parent, anchor = Tkinter.W, text = e).grid(row = self.r, sticky = Tkinter.W)
            self.r+=1
        self.entry_text = Tkinter.Entry(self.parent)
        self.entry_text.grid(row = 0, column = 1)
        self.button_update = Tkinter.Button(self.parent, text = "Update", command = self.update_gui).grid(row = 1, column = 1, sticky = Tkinter.E)

Finally, nothing is simpler than update_gui() function:

def update_gui(self):
        self.r+=1 # increment the row reserved to the new label
        self.Main_Q.append(self.entry_text.get())
        Tkinter.Label(self.parent, anchor = Tkinter.W, text = self.entry_text.get()).grid(row = self.r, sticky = Tkinter.W)

Programming the application:

Here is the full program:

'''
Created on Mar 11, 2016

@author: Bill BEGUERADJ
'''
import Tkinter


class Begueradj(Tkinter.Frame):
    def __init__(self, parent):
        Tkinter.Frame.__init__(self, parent)
        self.parent = parent
        self.main_queue = ["read", "clean dishes", "wash car"]
        self.r = 0
        self.initialize_user_interface()


    def initialize_user_interface(self):
        self.parent.title("Update GUI")
        self.parent.grid_rowconfigure(0, weight = 1)
        self.parent.grid_columnconfigure(0, weight = 1)

        for e in self.main_queue:
            Tkinter.Label(self.parent, anchor = Tkinter.W, text = e).grid(row = self.r, sticky = Tkinter.W)
            self.r+=1
        self.entry_text = Tkinter.Entry(self.parent)
        self.entry_text.grid(row = 0, column = 1)
        self.button_update = Tkinter.Button(self.parent, text = "Update", command = self.update_gui).grid(row = 1, column = 1, sticky = Tkinter.E)

    def update_gui(self):
        self.r+=1
        self.main_queue.append(self.entry_text.get())
        Tkinter.Label(self.parent, anchor = Tkinter.W, text = self.entry_text.get()).grid(row = self.r, sticky = Tkinter.W)


def main():
    root = Tkinter.Tk()
    b = Begueradj(root)
    root.mainloop()

if __name__ == "__main__":
    main()

Demo:

Here is a screenshot of the running program:

enter image description here

Note:

I coded the previous program using Python 2.7, so if you want to test it, please change Tkinter to tkinter. Everything else remains the same.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Billal Begueradj