MrRBM97
MrRBM97

Reputation: 169

Stop list multiplying when command called from button in tkinter

Below in a minimal reproducible example on my code and the problem i'm having.

from tkinter import *
from tkinter import messagebox

leagueGenerator = Tk()
leagueGenerator.title("Test")


def back_toStart():
    content = []
    children_widgets = frame2.winfo_children()
    for child_widget in children_widgets:
        if child_widget.winfo_class() == 'Entry':
            value = child_widget.get()
            content.append(value)
    print(content)
    frame1.tkraise()


def testVal(inStr, acttyp):
    if acttyp == '1':  # insert
        if not inStr.isdigit():
            return False
    return True


def createLeague():
    numTeams = entry1.get()
    if int(numTeams) > 16:
        messagebox.showerror("Invalid Input", "The number of team\nmust be below 16")
    elif int(numTeams) < 4:
        messagebox.showerror("Invalid Input", "The number of team\nmust be below 4")
    else:
        for i in range(int(numTeams)):
            lbl = Label(frame2, text=str(i + 1))
            lbl.grid(row=i + 3, column=1, sticky=E)

            entry = Entry(frame2, width=30)
            entry.grid(row=i + 3, column=2)

        frame2.tkraise()

# frame 1
frame1 = Frame(leagueGenerator, padx=20, pady=12)
frame1.grid(row=0, column=0, sticky=NSEW)

lbl1 = Label(frame1, text="Number between 4 and 16:")
lbl1.grid(row=2, column=3, padx=(5, 10))

entry1 = Entry(frame1, validate="key")
entry1['validatecommand'] = (entry1.register(testVal), '%P', '%d')
entry1.grid(row=2, column=4, padx=(0, 10))

btn1 = Button(frame1, command=createLeague, text="Continue", pady=5)
btn1.grid(row=3, column=4, pady=(20, 10))

# frame 2
frame2 = Frame(leagueGenerator, padx=20, pady=12)
frame2.columnconfigure(3, weight=1)
frame2.columnconfigure(4, weight=1)
frame2.grid(row=0, column=0, sticky=NSEW)

btn_back = Button(frame2, command=back_toStart, text="Back", width=14)
btn_back.grid(row=1, column=1, columnspan=2)


frame1.tkraise()

leagueGenerator.mainloop()

The problem im having is when I enter a number, ie 4, then press continue. It take to to the frame2 as I want. I then type in: A in 1, B in 2 ... and then press back. It then prints ['A', 'B', ...], again as expected. The probem come if i then press continue again, type the same thing into the entry's and the list printed is twice, ie ['A', 'B', 'C', 'D', 'A', 'B', 'C', 'D'], but im looking for it to just print the a,b,c,d once.

how would I go about fixing this? I've tried to reinitialise content = [] at the end of the back_toStart(), ie

    content = []
    default = []
    children_widgets = frame2.winfo_children()
    for child_widget in children_widgets:
        if child_widget.winfo_class() == 'Entry':
            value = child_widget.get()
            content.append(value)
    print(content)
    content = copy.deepcopy(default)

    frame1.tkraise()

but that doesn't work.

Any help would be much appreciated

Upvotes: 0

Views: 50

Answers (1)

Thingamabobs
Thingamabobs

Reputation: 8037

The issue that you are facing is that you create each time you press continue you create new entries. In the back_toStart you asking for all childs in frame2 while you didnt destroyed the older once. I was placing a list of your entries inside named my_entries and destroy them after printing out your content.

from tkinter import *
from tkinter import messagebox

leagueGenerator = Tk()
leagueGenerator.title("Test")


def back_toStart():
    content = []
    children_widgets = frame2.winfo_children()
    for child_widget in children_widgets:
        if child_widget.winfo_class() == 'Entry':
            value = child_widget.get()
            content.append(value)
    print(content)
    for entry in my_entries:
        entry.destroy()
    frame1.tkraise()


def testVal(inStr, acttyp):
    if acttyp == '1':  # insert
        if not inStr.isdigit():
            return False
    return True

my_entries=[]
def createLeague():
    numTeams = entry1.get()
    if int(numTeams) > 16:
        messagebox.showerror("Invalid Input", "The number of team\nmust be below 16")
    elif int(numTeams) < 4:
        messagebox.showerror("Invalid Input", "The number of team\nmust be below 4")
    else:
        for i in range(int(numTeams)):
            lbl = Label(frame2, text=str(i + 1))
            lbl.grid(row=i + 3, column=1, sticky=E)

            entry = Entry(frame2, width=30)
            my_entries.append(entry)
            entry.grid(row=i + 3, column=2)

        frame2.tkraise()

# frame 1
frame1 = Frame(leagueGenerator, padx=20, pady=12)
frame1.grid(row=0, column=0, sticky=NSEW)

lbl1 = Label(frame1, text="Number between 4 and 16:")
lbl1.grid(row=2, column=3, padx=(5, 10))

entry1 = Entry(frame1, validate="key")
entry1['validatecommand'] = (entry1.register(testVal), '%P', '%d')
entry1.grid(row=2, column=4, padx=(0, 10))

btn1 = Button(frame1, command=createLeague, text="Continue", pady=5)
btn1.grid(row=3, column=4, pady=(20, 10))

# frame 2
frame2 = Frame(leagueGenerator, padx=20, pady=12)
frame2.columnconfigure(3, weight=1)
frame2.columnconfigure(4, weight=1)
frame2.grid(row=0, column=0, sticky=NSEW)

btn_back = Button(frame2, command=back_toStart, text="Back", width=14)
btn_back.grid(row=1, column=1, columnspan=2)


frame1.tkraise()

leagueGenerator.mainloop()

Upvotes: 1

Related Questions