2

I am trying to pull data from a Tkinter entry into a variable to use later - I'm currently trying to print it to shell for testing purposes - however, whenever I try and print the variable to shell it says "pname not defined" - pname being the name of the variable.

Code:

# Imports necesary modules
import sys, os, time
import winsound as ws
import tkinter as tk

# Creates window
gui = tk.Tk()
gui.title('Tiemer Niptus')
gui.geometry('1920x1080')
gui.configure(bg='#572f87')
#gui.wm_iconbitmap('resources\images\icon.ico')

# Defines prerequisite functions
def gt_play():
    ws.PlaySound('resources\sound\gt.wav', ws.SND_FILENAME|ws.SND_LOOP|ws.SND_ASYNC)

def win_play():
    ws.PlaySound('resources\sound\win.wav', ws.SND_FILENAME|ws.SND_LOOP|ws.SND_ASYNC)

def dth_play():
    ws.PlaySound('resources\sound\dth.wav', ws.SND_FILENAME|ws.SND_LOOP|ws.SND_ASYNC)

def snd_stop():
    ws.PlaySound(None, ws.SND_FILENAME|ws.SND_PURGE)

def death():
    dth_play()
    gui.configure(bg='#000000')
    
    dth_lbl = tk.Label(text='YOU HAVE DIED', font = ['Helvetica', 60], bg='#000000', fg='#a50b29')
    dth_lbl.pack()
    dth_lbl.place(x=950, y=370, anchor="center")

    dth_btn = tk.Button(text='TRY AGAIN?', font = ['Helvetica', 60], bg='#a50b29', fg='#000000',
                        command = lambda:[dth_lbl.destroy(), dth_btn.destroy(), snd_stop(), str_screen()])
    dth_btn.pack()
    dth_btn.place(x=950, y=500, anchor="center")

def win():
    win_play()
    gui.configure(bg='#1dcc0d')
    
    win_lbl = tk.Label(text='YOU HAVE WON!', font = ['Helvetica', 60], bg='#1dcc0d', fg='#ffd700')
    win_lbl.pack()
    win_lbl.place(x=950, y=370, anchor="center")

    win_btn = tk.Button(text='PLAY AGAIN?', font = ['Helvetica', 60], bg='#1dcc0d', fg='#ffd700',
                        command = lambda:[win_lbl.destroy(), win_btn.destroy(), snd_stop(), str_screen()])
    win_btn.pack()
    win_btn.place(x=950, y=500, anchor="center")

# Defines stage functions
def str_screen():
    gt_play()
    gui.configure(bg='#572f87')
    
    str_lbl = tk.Label(text='TIEMER NIPTUS', font = ['Helvetica', 60], fg='#00ffab', bg='#572f87')
    str_lbl.pack()
    str_lbl.place(x=950, y=350, anchor="center")

    str_btn = tk.Button(text='START', font = ['Helvetica', 50], bg='#7d0234', fg='#00ffab', width = 15,
                        command = lambda:[str_lbl.destroy(), str_btn.destroy(), name_select()])
    str_btn.pack()
    str_btn.place(x=950, y=475, anchor="center")

def name_select():
    pname_lbl = tk.Label(text='INPUT NAME', fg='#00ffab', font = ['Helvetica', 50], bg='#572f87')
    pname_lbl.pack()
    pname_lbl.place(x=950, y=340, anchor="center")

    pname_ent = tk.Entry(bg='#00ffab', fg='#7d0234', font = ['Helvetica', 40], width = 14)
    pname_ent.pack()
    pname_ent.place(x=950, y=415, anchor="center")
    pname = pname_ent.get()
    
    go_btn = tk.Button(text='GO', font = ['Helvetica', 25], bg='#7d0234', fg='#00ffab', width = 21,
                       command = lambda:[snd_stop(), pname_lbl.destroy(), pname_ent.destroy(), go_btn.destroy(), street()])
    go_btn.pack()
    go_btn.place(x=950, y=490, anchor='center')
 
def street():
    print(pname)
    
# Draws window and starts game
str_screen()
gui.mainloop()

Error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\lucas\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 1550, in __call__
    return self.func(*args)
  File "C:\Users\lucas\Desktop\Program\TiemerNiptus.py", line 77, in <lambda>
    command = lambda:[snd_stop(), pname_lbl.destroy(), pname_ent.destroy(), go_btn.destroy(), street()])
  File "C:\Users\lucas\Desktop\Program\TiemerNiptus.py", line 82, in street
    print(pname)
NameError: name 'pname' is not defined
Nimantha
  • 6,405
  • 6
  • 28
  • 69
TJF
  • 23
  • 4
  • 5
    Scoping error - the variable is not known inside `def street()`. You either need to pass it in as variable, provide it as classvariable (for a instance that you know in the scope of your function) or declare it as global (you also would have to set it `global` in `def name_select():` so it sets the _global_ one, not a _local_ one with the same name. Probably best to use a class instance that you can reference throughout your game instead of creating multiple global ones.... – Patrick Artner Jun 14 '18 at 06:54
  • Don't do globals - (or at least read [use-of-global-keyword-in-python](https://stackoverflow.com/questions/4693120/use-of-global-keyword-in-python) ) – Patrick Artner Jun 14 '18 at 06:58
  • Thanks @PatrickArtner : 2 things. 1: My code no longer throws an exception using global pname, however it doesn't print anything to shell, no matter what was input in the entity box. 2: I would love to try a class, or classvariable but haven't got to that point yet. If you could explain, basically, what they are and how they work that would be great! – TJF Jun 14 '18 at 08:31

1 Answers1

1

From my comment:

Scoping error - the variable is not known inside def street(). You either need to pass it in as variable, provide it as classvariable (for a instance that you know in the scope of your function) or declare it as global .

If you want to learn about classes, go through the documentation: https://docs.python.org/3.6/tutorial/classes.html

For a basic approach, see comments inside code:

# Imports necesary modules
import sys, os, time
import winsound as ws
import tkinter as tk

class MyData:
    """This is a bad example for oop. Normaly classes link data (state) with behavior. 
    For now this has data, no behavior (I cheated some behaviour into it ;). 
    Its use is more of a container for data that you pass around - if thats the only 
    thing it will ever do, use a dictionary as 'key=value' store instead."""
    def __init__(self):
        self.pname = ""

    def FancyName(self):
        """Returns self.pname in an UpPeR LoWeR CaSe mAnNeR"""
        return ''.join(x.upper() if i % 2 == 0 else x.lower() for i,
                       x in enumerate(self.pname))


# create data storage class instance
myData = MyData ()   # use a dictionary until you need "behaviour"

# left out more of your code

def name_select():
    global myData
    pname_lbl = tk.Label(text='INPUT NAME', fg='#00ffab', font = ['Helvetica', 50], 
                         bg='#572f87')
    pname_lbl.pack()
    pname_lbl.place(x=950, y=340, anchor="center")

    pname_ent = tk.Entry(bg='#00ffab', fg='#7d0234', 
                         font = ['Helvetica', 40], width = 14)
    pname_ent.pack()
    pname_ent.place(x=950, y=415, anchor="center")
    myData.pname = pname_ent.get() # at this time, pname_ent.get() is still empty, you 
                                   # need to capture the value when the GO button 
                                   # is pressed

    # not sure if this syntax works, cant try right now. capture the pname_ent.get() value
    # as 'lname' and provide it to the street() function, you destroy your inputs    
    # here, so no way to get to the values when already inside street() ...
    go_btn = tk.Button(text='GO', font = ['Helvetica', 25], bg='#7d0234', fg='#00ffab', 
                       width = 21, 
                       command = lambda lname = pname_ent.get():[snd_stop(), 
                                     pname_lbl.destroy(), pname_ent.destroy(), 
                                     go_btn.destroy(), street(lname)])
    go_btn.pack()
    go_btn.place(x=950, y=490, anchor='center')

def street(n):
    global myData
    myData.pname = n
    print(myData.FancyName())
Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
  • Thanks for all the help so far! Could you help me understand why my current code still isn't working, please? – TJF Jun 14 '18 at 09:57
  • @TJF no idea what your current problem is - your "player name not defined" should be solved. Create a new question with a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve) that replicates what you encounter now. Use a debugger to see where the player name does get set and where it is no longer set: [How to debug small programs (#1)](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) – Patrick Artner Jun 14 '18 at 10:02