Skip to content
Advertisement

Tkinter function creates variable that can’t be added to list with .get() from entry

First off, I am aware that there are many questions out there with .get() not properly working and I have read through many of them. My issue is that my program has a button that every time it is pressed, it adds a new entry box for a new Player to be added, then I then want to create a Player object (I have the player class defined in another file) and add the Player object to a list. Here is the function for the “Add Player” button:

def add_player():
    new_player = Label(team_wind, text='Enter an NBA Player:')
    new_player_entry = Entry(team_wind, width=30)
    new_player.pack()
    new_player_entry.pack()
    team_wind.mainloop()
    player_list.append(new_player_entry.get())

(team_wind is the window because it is creating a Team of Players. the Team class is also defined in another file) After some reaserch, I realized that mainloop would terminate that block of code (as far as my understanding). So, when I run the program, the entry returns ”. I know this is a very common issue, but it is wierd for mine because I can’t figure out a way to get around it. I already have a working part of the tkinter window for a single player with a single entry box, so I know how .get() works. I’ve tried using .update() and .update_idletasks().

  • I have tried moving the player_list.append to before the mainloop because I know the code after is unreachable, but if I move it to before, then it returns nothing

. If I try to do it in another function or after the code terminates, then it won’t work because if the button is pressed multiple times, each entry will have the same variable name. I think this means it has to be done in this function, but not sure how to do that with mainloop. Here is the code to create the window so it will run. All I need is for it to be able to print or return the list with the player objects for however many players there are (depends how many times the button is pressed). I have provided the code needed to run the program and cut out everything else that would cause errors. Thanks

     from tkinter import *
    player_list = []    
    def add_player():
        new_player = Label(team_wind, text='Enter an NBA Player:')
        new_player_entry = Entry(team_wind, width=30)
        new_player.pack()
        new_player_entry.pack()
        team_wind.mainloop()
        player_list.append(new_player_entry.get())
    
    def main():
        #setup
        global team_name
        global team_wind
        global player_entry
        global player_entry2
        team_wind = Tk()
        team_wind.title('Team')
        team_wind.geometry('800x500')
    
        #Text entries
        team_mode_title = Label(team_wind, text='Make a team of NBA Players and find their stats')
        player = Label(team_wind, text='Enter an NBA Player:')
        player2 = Label(team_wind, text='Enter an NBA Player:')
        
        #Text Box Entries
        player_entry = Entry(team_wind, width=30)
        player_entry2 = Entry(team_wind, width=30)
    
        #BUTTONS
        add_player_button = Button(team_wind, text='Add player', command=add_player)
    

        #Button for StackOverflow question to print the list of players
            print_list_button = Button(team_wind, text='Print List', command=print_list)
            #Pack
            team_mode_title.pack()
            #avg_button.pack()
            add_player_button.pack()
            print_list_button.pack()
            player.pack()
            player_entry.pack()
       

 player2.pack()
        player_entry2.pack()
    
        team_wind.mainloop()
    

def print_list():
    player_list.append(player_entry.get())
    player_list.append(player_entry2.get())
    print(player_list)

if __name__ == "__main__":
    main()

Advertisement

Answer

You should have only one mainloop() – in main().

You could use your list to keep widgets Entry – without using .get() – and you should use .get() when you print list.


Minimal working code.

I used Frame to keep Label and Entry and this way it adds Entry before Buttons.

import tkinter as tk  # PEP8: `import *` is not preferred

def add_player():
    label = tk.Label(frame, text='Enter an NBA Player:')
    label.pack()
    
    entry = tk.Entry(frame, width=30)
    entry.pack()
    
    entry_list.append( entry )  # add full widget, not value from widget

def print_list():
    for number, entry in enumerate(entry_list, 1):
        print( number, entry.get() )

def main():
    global team_wind
    global frame

    team_wind = tk.Tk()
    team_wind.title('Team')
    team_wind.geometry('800x500')

    team_mode_title = tk.Label(team_wind, text='Make a team of NBA Players and find their stats')
    team_mode_title.pack()

    # frame to keep all Entries
    frame = tk.Frame(team_wind)
    frame.pack()
    
    # at start add Entries for two players
    add_player()    
    add_player()
    
    # button to add Entry for next player
    add_player_button = tk.Button(team_wind, text='Add player', command=add_player)
    add_player_button.pack()

    # button to print values from all Entries
    print_list_button = tk.Button(team_wind, text='Print List', command=print_list)
    print_list_button.pack()

    team_wind.mainloop()

# --- main ---

entry_list = []

main()
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement