Search code examples
pythonpython-3.xloopstkintertreeview

How can I insert values into a Treeview using a function and a loop? (not insert)


I would like to insert the values 4, 1, 7, 5, 9, 3 into the Badge column of the Treeviews, using column = function() (not treeview.insert) and loop

As you can see, i unpacked each list and then repacked it with Rank = record[0], Name = record[1], and Badge = example(). And also i use values = datagrid. I know there are better ways, but I need to maintain this code.

Currently in the Badge column of the Treeview I see 4, 4, 4, 4, 4, 4. Instead I would like to print 4, 1, 7, 5, 9, 3

from tkinter import *
from tkinter import ttk

ws = Tk()
ws.title('PythonGuides')
ws.geometry('400x300')
ws['bg']='#fb0'

data  = [
    [1,"Jack"],
    [2,"Tom"],
    [3,"Daniel"],
    [4,"Leonard"],
    [5,"Frank"],
    [6,"Robert"],
    ]

tv = ttk.Treeview(ws)
tv['columns']=('Rank', 'Name', 'Badge')
tv.column('#0', width=0, stretch=NO)
tv.column('Rank', anchor=CENTER, width=80)
tv.column('Name', anchor=CENTER, width=80)
tv.column('Badge', anchor=CENTER, width=80)
tv.heading('#0', text='', anchor=CENTER)
tv.heading('Rank', text='Id', anchor=CENTER)
tv.heading('Name', text='rank', anchor=CENTER)
tv.heading('Badge', text='Badge', anchor=CENTER)
tv.pack()


def func1():

    def example():
        x  = [
            ["4"],
            ["1"],
            ["7"],
            ["5"],
            ["9"],
            ["3"],
            ]

        for a in x:
            return a

    for index, record in enumerate(data):
        Rank = record[0]
        Name = record[1]
        Badge = example()
        
        datagrid = [Rank, Name, Badge]
        tv.insert(parent='', index='end', values=(datagrid))

   

button = Button(ws, text="Button", command = func1)
button.place(x=1, y=1)

ws.mainloop()

Solution

  • Using return in function it will allways run all code in function from the beginning and it will always use first element from list.

    You have to use yield instead of return. It will create generator and it will need also next() to get next value from generator.

    def example():
        x  = [
            ["4"],
            ["1"],
            ["7"],
            ["5"],
            ["9"],
            ["3"],
            ]
    
        for a in x:
            yield a
    
    gen = example()   
    
    for index, record in enumerate(data):
        Rank = record[0]
        Name = record[1]
        Badge = next(gen)
    
        # ... rest ...
    

    You may also use generator directly in for without next() (it needs ( ) after for to correctly assign values from zip())

    gen =  example()   
    
    for (index, record), Badge in zip(enumerate(data), gen):
        Rank = record[0]
        Name = record[1]
    
        # ... rest ...
    

    But frankly, I would use directly x without creating example()

    x  = [["4"],["1"],["7"],["5"],["9"],["3"],]
    
    for (index, record), Badge in zip(enumerate(data), x):
        Rank = record[0]
        Name = record[1]
    
        # ... rest ...