I'm developing a GUI for a simple PC game in Python, and I am currently having difficulties with storing a value that the program prompts a user to input through a tkinter.Entry widget. I have used this widget successfully before with the same logic that I have provided in my code below and yet, I am receiving a traceback: 'NameError object not defined'. In particular, when I run the program, a canvas widget and accompanying button, label, and entry widgets are successfully generated. However, when I input a string through the entry field widget and activate the "Submit" button, the interpreter gives me an error indicating that the object I am storing the input in isn't defined. Then, when I activate the "Start Flipping" button, the animation does not start, and I receive a second traceback error: "command=lambda : animation(count))NameError: name 'animation' is not defined Please see the code and traceback error below."
Thanks in advance for the help and consideration! :) (PS: Don't worry about the naming conventions; this snippet is part of a larger program that doesn't affect this code's functionality, and I have tried using tkinter.Tk() as an alternative to tkinter.Toplevel() to no avail).
import tkinter
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
import time
import os
import PIL
from PIL import ImageTk
import glob
import random
root_2 = tkinter.Toplevel()
root_2.geometry('800x800')
root_2.title("Determination of Turn Order")
''' The code below is for implementing a window widget for:
1) Displaying message to user that will call coin flip
2) Prompting user to call coin flip
3) Prompting user to run coin flip simulation
4) Displaying message to users to reflect coin flip outcome
5) Displaying message to users to reflect turn order
'''
player1 = "Justin"
player2 = "Jaclyn"
# Define Canvas widget to overlay entry and label widgets on turn order window
canvas_3 = tkinter.Canvas(root_2,width=800,height=800)
canvas_3.pack(expand = tkinter.TRUE, fill = tkinter.BOTH) # Set width and height parameters
# Create Label widget to display message to user that will call coin flip
user_coin_call_label = tkinter.Label(canvas_3, text = player1 + " Will Call The Coin Flip", font=('calibre',30,'bold'))
user_coin_call_label.pack()
user_coin_call_label.place(x=100,y=0)
# # Create dialogue-button widget to read in text from user
# Declare "StringVar" object for storing coin text input
global coin_guess, coin_guess_obj
coin_guess_obj = tkinter.StringVar()
# Define function that will read in coin guess from Entry widget
def input_guess():
''' This function reads in coin guess from Entry widget'''
global coin_guess, coin_guess_obj
coin_guess = coin_guess_obj.get()
#coin_guess_obj.set("")
#root.destroy()
def destroy_turn_order_win():
root_2.destroy()
# Define label for prompting player to input coin flip gues
user_coin_input_label = tkinter.Label(canvas_3, text = player1 + ", please input coin flip guess (H/T)")
#user_coin_input_label.pack()
user_coin_input_label.place(x=0,y=50)
# Define entry field for coin flip guess input using Entry widget
user_coin_input_entry = tkinter.Entry(canvas_3, textvariable = coin_guess_obj, width=20)
#user_coin_input_entry.pack()
user_coin_input_entry.place(x=220, y=50)
# Define button for submitting coin flip guess using Button widget
submit_guess_button=tkinter.Button(canvas_3, text="Submit", command=input_guess)
#submit_guess_button.pack()
submit_guess_button.place(x=0, y=75)
# Define label for prompting player to run and stop coin flip simulation:
start_stop_coin_sim_label = tkinter.Label(canvas_3, text = player1 + ", please start and stop coin a flip simulation using the buttons below")
#start_stop_coin_sim_label.pack()
start_stop_coin_sim_label.place(x=0, y=100)
# Load image frames of coin toss gif
filename = 'coin_toss_1.gif'
file_opn = PIL.Image.open(filename)
frame_num = file_opn.n_frames
im = [ImageTk.PhotoImage(file=filename, format = f'gif -index {i}') for i in range(frame_num)]
global coin_frame, coin_outcome, anim
anim = None
count = 0
def animation(count):
''' This function animates the gif by displaying successive frames
on a label widget '''
global anim, coin_frame
im2 = im[count]
gif_label.configure(image=im2)
print(count)
# self.coin_frame = count to store frame as data member and associate with known coin outcome
coin_frame = count
count += 1
if count == frame_num:
count = 0
anim = canvas_3.after(0, lambda : animation(count))
def set_coin_outcome():
''' This function compares the coin frame number of the last frame
loaded in the animation() call to relationships between frame numbers
and associated coin outcomes to store the coin toss outcome '''
# Place holder to test stop_animation() call of set_coin_outcome:
global coin_frame, coin_outcome
#print("heads")
if (coin_frame == 0):
# heads outcome
coin_outcome = "H"
elif (coin_frame == 1):
# tails outcome
coin_outcome = "T"
elif ((coin_frame %2) == 1):
# tails outcome
coin_outcome = "T"
else:
# heads outcome
#self.coin_outcome = heads
coin_outcome = "H"
def stop_animation():
''' This function terminates the "animation()" function
which stops the frame animation of the gif '''
global anim, coin_frame, coin_outcome
canvas_3.after_cancel(anim)
set_coin_outcome()
im_base = [ImageTk.PhotoImage(file=filename, format = f'gif -index {0}')]
gif_label = tkinter.Label(canvas_3, image=im_base)
#gif_label.pack()
gif_label.place(x = 240, y = 300)
start_button = tkinter.Button(canvas_3, text="Start Flipping", command=lambda : animation(count))
#start_button.pack()
start_button.place(x=350, y=250)
stop_button = tkinter.Button(canvas_3, text="Stop Flipping", command=stop_animation)
#stop_button.pack()
stop_button.place(x=350, y=275)
#coin_outcome = "H" # Placeholder
if (coin_guess == "H" and coin_outcome == "H"):
turn_order_label = tkinter.Label(canvas_3, text = player1 + ", you will have the first turn")
#turn_order_label.pack()
turn_order_label.place(x=240, y=500)
elif(coin_guess == "T" and coin_outcome == "T"):
turn_order_label = tkinter.Label(canvas_3, text = player1 + ", you will have the first turn")
#turn_order_label.pack()
turn_order_label.place(x=240, y=500)
else:
turn_order_label = tkinter.Label(canvas_3, text = player2 + ", you will have the first turn")
#turn_order_label.pack()
turn_order_label.place(x=240, y=500)
continue_game_button=tkinter.Button(canvas_3, text="Continue Game", command=destroy_turn_order_win)
#continue_game_button.pack()
continue_game_button.place(x=300,y=550)
canvas_3.mainloop()
'''
Traceback Error 1:
Exception in Tkinter callback
Traceback (most recent call last):
File "/Applications/anaconda3/lib/python3.8/tkinter/__init__.py", line 1883, in __call__
return self.func(*args)
File "/Users/jcam98/Desktop/Programming_Applications/Python/Practice_Scripts/tkinter_gui_tutorial.py", line 348, in input_guess
coin_guess = coin_guess_obj.get()
NameError: name 'coin_guess_obj' is not defined
Traceback Error 2:
Exception in Tkinter callback
Traceback (most recent call last):
File "/Applications/anaconda3/lib/python3.8/tkinter/__init__.py", line 1883, in __call__
return self.func(*args)
File "/Users/jcam98/Desktop/Programming_Applications/Python/Practice_Scripts/tkinter_gui_tutorial.py", line 474, in <lambda>
start_button = tkinter.Button(canvas_3, text="Start Flipping", command=lambda : animation(count))
NameError: name 'animation' is not defined
'''
[Current state of GUI][1]
[1]: https://i.stack.imgur.com/Em0P5.png