Can do I condense this code for making multiple labels and entries depending on a variable?

Viewed 30

I have created a scale to select how many players there are, then by pressing a button, it sends you to the page where you input the names of each player, of which they are put into a list for later use.

The problem is, it takes up loads of space and I feel like there is most definitely a way to condense this.

def playerset():
    title.configure(text="Set amount of players:", font=("Arial", 20))
    eir.grid_remove()
    pit.grid_remove()
    playerbut.grid_remove()
    player = IntVar()
    playerscale = Scale(window, from_=1, to=12, width=30, length=300, orient=HORIZONTAL, variable=player)
    playerscale.grid(column=0, row=1)

    def playernext():
        players=int(player.get())
        title.configure(text="Name each player:", font=("Arial", 20))
        playernextbut.grid_forget()
        playerscale.grid_forget()
        if (players > 0):
            player1dis = Label(window, text="Player 1", font=("Arial", 15))
            player1dis.grid(column=0, row=1)
            player1 = StringVar()
            p1 = Entry(window, width=20, textvariable=player1, font=("Arial", 15))
            p1.grid(column=1, row=1)
            if (players > 1):
                player2dis = Label(window, text="Player 2", font=("Arial", 15))
                player2dis.grid(column=0, row=2)
                player2 = StringVar()
                p2 = Entry(window, width=20, textvariable=player2, font=("Arial", 15))
                p2.grid(column=1, row=2)
                if (players > 2):
                    player3dis = Label(window, text="Player 3", font=("Arial", 15))
                    player3dis.grid(column=0, row=3)
                    player3 = StringVar()
                    p3 = Entry(window, width=20, textvariable=player3, font=("Arial", 15))
                    p3.grid(column=1, row=3)
                    if (players > 3):
                        player4dis = Label(window, text="Player 4", font=("Arial", 15))
                        player4dis.grid(column=0, row=4)
                        player4 = StringVar()
                        p4 = Entry(window, width=20, textvariable=player4, font=("Arial", 15))
                        p4.grid(column=1, row=4)
                        if (players > 4):
                            player5dis = Label(window, text="Player 5", font=("Arial", 15))
                            player5dis.grid(column=0, row=5)
                            player5 = StringVar()
                            p5 = Entry(window, width=20, textvariable=player5, font=("Arial", 15))
                            p5.grid(column=1, row=5)
                            if (players > 5):
                                player6dis = Label(window, text="Player 6", font=("Arial", 15))
                                player6dis.grid(column=0, row=6)
                                player6 = StringVar()
                                p6 = Entry(window, width=20, textvariable=player6, font=("Arial", 15))
                                p6.grid(column=1, row=6)
                                if (players > 6):
                                    player7dis = Label(window, text="Player 7", font=("Arial", 15))
                                    player7dis.grid(column=0, row=7)
                                    player7 = StringVar()
                                    p7 = Entry(window, width=20, textvariable=player7, font=("Arial", 15))
                                    p7.grid(column=1, row=7)
                                    if (players > 7):
                                        player8dis = Label(window, text="Player 8", font=("Arial", 15))
                                        player8dis.grid(column=0, row=8)
                                        player8 = StringVar()
                                        p8 = Entry(window, width=20, textvariable=player8, font=("Arial", 15))
                                        p8.grid(column=1, row=8)
                                        if (players > 8):
                                            player9dis = Label(window, text="Player 9", font=("Arial", 15))
                                            player9dis.grid(column=0, row=9)
                                            player9 = StringVar()
                                            p9 = Entry(window, width=20, textvariable=player9, font=("Arial", 15))
                                            p9.grid(column=1, row=9)
                                            if (players > 9):
                                                player10dis = Label(window, text="Player 10", font=("Arial", 15))
                                                player10dis.grid(column=0, row=10)
                                                player10 = StringVar()
                                                p10 = Entry(window, width=20, textvariable=player10, font=("Arial", 15))
                                                p10.grid(column=1, row=10)
                                                if (players > 10):
                                                    player11dis = Label(window, text="Player 11", font=("Arial", 15))
                                                    player11dis.grid(column=0, row=11)
                                                    player11 = StringVar()
                                                    p11 = Entry(window, width=20, textvariable=player11, font=("Arial", 15))
                                                    p11.grid(column=1, row=11)
                                                    if (players > 11):
                                                        player12dis = Label(window, text="Player 12", font=("Arial", 15))
                                                        player12dis.grid(column=0, row=12)
                                                        player12 = StringVar()
                                                        p12 = Entry(window, width=20, textvariable=player12, font=("Arial", 15))
                                                        p12.grid(column=1, row=12)

        def playersubmit():
            title.configure(text="-----Welcome to the Rottot Games Interface!-----", font=("Arial", 30))
            eir.grid()
            pit.grid()
            playerbut.grid()
            playersubmitbut.grid_forget()
            if (players > 0):
                p1name=str(player1.get())
                plist = [p1name]
                player1dis.grid_forget()
                p1.grid_forget()
                if (players > 1):
                    p2name=str(player2.get())
                    plist = [p1name, p2name]
                    player2dis.grid_forget()
                    p2.grid_forget()
                    if (players > 2):
                        p3name=str(player3.get())
                        plist = [p1name, p2name, p3name]
                        player3dis.grid_forget()
                        p3.grid_forget()
                        if (players > 3):
                            p4name=str(player4.get())
                            plist = [p1name, p2name, p3name, p4name]
                            player4dis.grid_forget()
                            p4.grid_forget()
                            if (players > 4):
                                p5name=str(player5.get())
                                plist = [p1name, p2name, p3name, p4name, p5name]
                                player5dis.grid_forget()
                                p5.grid_forget()
                                if (players > 5):
                                    p6name=str(player6.get())
                                    plist = [p1name, p2name, p3name, p4name, p5name, p6name]
                                    player6dis.grid_forget()
                                    p6.grid_forget()
                                    if (players > 6):
                                        p7name=str(player7.get())
                                        plist = [p1name, p2name, p3name, p4name, p5name, p6name, p7name]
                                        player7dis.grid_forget()
                                        p7.grid_forget()
                                        if (players > 7):
                                            p8name=str(player8.get())
                                            plist = [p1name, p2name, p3name, p4name, p5name, p6name, p7name, p8name]
                                            player8dis.grid_forget()
                                            p8.grid_forget()
                                            if (players > 8):
                                                p9name=str(player9.get())
                                                plist = [p1name, p2name, p3name, p4name, p5name, p6name, p7name, p8name, p9name]
                                                player9dis.grid_forget()
                                                p9.grid_forget()
                                                if (players > 9):
                                                    p10name=str(player10.get())
                                                    plist = [p1name, p2name, p3name, p4name, p5name, p6name, p7name, p8name, p9name, p10name]
                                                    player10dis.grid_forget()
                                                    p10.grid_forget()
                                                    if (players > 10):
                                                        p11name=str(player11.get())
                                                        plist = [p1name, p2name, p3name, p4name, p5name, p6name, p7name, p8name, p9name, p10name, p11name]
                                                        player11dis.grid_forget()
                                                        p11.grid_forget()
                                                        if (players > 11):
                                                            p12name=str(player12.get())
                                                            plist = [p1name, p2name, p3name, p4name, p5name, p6name, p7name, p8name, p9name, p10name, p11name, p12name]
                                                            player12dis.grid_forget()
                                                            p12.grid_forget()

            import pickle
            with open("Players.txt", "wb") as playersave:
                pickle.dump(plist, playersave)

        playersubmitbut = Button(window, text="Submit", command=playersubmit, font=("Arial", 15), bg="green", fg="black")
        playersubmitbut.grid(column=4, row=0)

    playernextbut = Button(window, text="Next", command=playernext, font=("Arial", 20), bg="green", fg="black")
    playernextbut.grid(column=4, row=1)

playerbut = Button(window, text="Set Players", command=playerset, font=("Arial", 20), bg="gray", fg="black")
playerbut.grid(column=1, row=2)

Apologies for all the code, Thank you!

2 Answers

Without going into the tkinter specifics too much, it looks like this can be done with a loop and a dictionary.

A more robust approach could be to use a class for a Player, that would store all the relevant information.

Example below includes the player name and the playerdis label, but not anything else. You can expand it to include any information/widget you need to keep track of.

def playerset():

    ### CONFIG STUFF HERE ###

    def playernext():
        players=int(player.get())
        ### CONFIG STUFF ### 
        player_info = {} # dictionary of dictionaries to store references to stringvars, pidsgrids etc for each player id
        for player_index in range(players):
            playerdis = Label(window, text="Player "+str(player_index)) # change formatting as necessary
            player_info[player_index] = {}  # make an empty subdictionary for this player
            player_info[player_index]['label'] = playerdis  # store reference to the label
            player_info[player_index]['name'] = StringVar() # store reference to the stringvar
            name_entry = Entry(window, width=20, textvariable= player_info[player_index]['name'])

            ### MORE CONFIG STUFF ###   
    return player_info  # return the populated dictionary of references for later use

And then further down when you need to use this information:

def playersubmit(player_info):
            ### CONFIG STUFF ###
            playersubmitbut.grid_forget()
            for player_index in player_info.keys():
                pname=str(player_info[player_index]['name'].get()) # get the name from the StringVar reference
                plist = [pname]
                player_info[player_index]['label'].grid_forget()  # access the label and forget
                ### CONFIG STUFF ###

You can use classes to modularize your code, and deal with specialized small entities that do one thing well:

Maybe a class Player to hold the info relevant to a player, a class Players to hold a collection of players?

Your App code can also be modularized: The following toy example has a main App that has 3 buttons that control the pop of a Toplevel window to enter the number of players, another to enter the specifics of each player, and lastly, one that prints the players in the collection.

import tkinter as tk


class Player:
    """Represents a Player in the game
    """
    ID = 0

    def __init__(self, name):
        self.name = name
        self.id = self.make_id()

    def make_id(self):
        Player.ID += 1
        return Player.ID - 1

    def __str__(self):
        return f'Player {self.id}, {self.name}'


class Players:
    """A collection of Players
    """

    def __init__(self):
        self.players = []

    def add_player(self, player):
        self.players.append(player)

    def __iter__(self):
        for player in self.players:
            yield player

    def __len__(self):
        return len(self.players)


class App(tk.Tk):
    """The app itself
    """

    def __init__(self):
        super().__init__()
        self.players = Players()
        self.num_players = 0
        tk.Button(self, text='get number of players', command = self.get_num_players).pack()
        tk.Button(self, text='build a players', command = self.build_players).pack()
        tk.Button(self, text='print list players', command=lambda: print(str(self))).pack()

    def get_num_players(self):
        NumPlayerEntry(self)

    def build_players(self):
        if len(self.players) < self.num_players:
            PlayerBuilder(self)

    def __str__(self):
        res = []
        for player in self.players:
            res.append(str(player))
        return '\n'.join(res)


class NumPlayerEntry(tk.Toplevel):
    """popup that allows to enter the number of players in the game
    """

    def __init__(self, master):
        self.master = master
        super().__init__(master)
        tk.Label(self, text='enter number of players').pack()
        self.entry = tk.Entry(self)
        self.entry.pack()
        tk.Button(self, text='confirm', command=self.confirm_num_players).pack()

    def confirm_num_players(self):
        self.master.num_players = int(self.entry.get())
        self.destroy()


class PlayerBuilder(tk.Toplevel):
    """popup that allows to enter the characteristics of a player
    """

    def __init__(self, master):
        self.master = master
        super().__init__(master)
        tk.Label(self, text='add player (enter name)').pack()
        self.entry = tk.Entry(self)
        self.entry.pack()
        tk.Button(self, text='confirm', command=self.make_player).pack()

    def make_player(self):
        self.master.players.add_player(Player(self.entry.get()))
        self.destroy()


App().mainloop()
Related