Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #63854 > unrolled thread

Tkinter GUI Error

Started byfluttershy363@gmail.com
First post2014-01-13 10:49 -0800
Last post2014-01-14 22:33 +0100
Articles 11 — 7 participants

Back to article view | Back to comp.lang.python


Contents

  Tkinter GUI Error fluttershy363@gmail.com - 2014-01-13 10:49 -0800
    Re: Tkinter GUI Error Lewis Wood <fluttershy363@gmail.com> - 2014-01-13 10:51 -0800
    Re: Tkinter GUI Error Christian Gollwitzer <auriocus@gmx.de> - 2014-01-13 20:03 +0100
      Re: Tkinter GUI Error Lewis Wood <fluttershy363@gmail.com> - 2014-01-13 11:21 -0800
    Re: Tkinter GUI Error Peter Otten <__peter__@web.de> - 2014-01-13 20:36 +0100
    Re: Tkinter GUI Error Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2014-01-13 20:39 -0500
    Re: Tkinter GUI Error Rick Johnson <rantingrickjohnson@gmail.com> - 2014-01-13 18:47 -0800
    Re: Tkinter GUI Error Chris Angelico <rosuav@gmail.com> - 2014-01-14 14:12 +1100
      Re: Tkinter GUI Error Lewis Wood <fluttershy363@gmail.com> - 2014-01-14 11:11 -0800
        Re: Tkinter GUI Error Lewis Wood <fluttershy363@gmail.com> - 2014-01-14 13:27 -0800
          Re: Tkinter GUI Error Christian Gollwitzer <auriocus@gmx.de> - 2014-01-14 22:33 +0100

#63854 — Tkinter GUI Error

Fromfluttershy363@gmail.com
Date2014-01-13 10:49 -0800
SubjectTkinter GUI Error
Message-ID<1ab2aa93-1ba6-48b0-a5f4-5fb05cb523d1@googlegroups.com>
Inside the function is where I am having the problem, I am trying to get it to delete the label so that it may then replace it with a shorter text.
Here is the full code:




from tkinter import *
import random
main = Tk()
main.title("Crack the Code")

def check1():
    entry = entry1var.get()
    if entry == num1:
        labelent1.destroy()
        labelent1 = Label(main, text="Correct!",fg="green").grid(row = 0, column = 3)
    elif entry > num1:
        labelent1.destroy()
        labelent1 = Label(main, text="Too Big",fg="red").grid(row = 0, column = 3)
    elif entry < num1:
        labelent1.destroy()
        labelent1 = Label(main, text="Too Small",fg="red").grid(row = 0, column = 3)




global num1
global num2
global num3
num1 =str(random.randint(10,99))
num2 =str(random.randint(10,99))
num3 =str(random.randint(10,99))
mastercode = num1+num2+num3


entry1var = StringVar()
entry2var = StringVar()
entry3var = StringVar()


number1 = Label(main, text="Number 1").grid(row = 0, column = 0)
number2 = Label(main, text="Number 2").grid(row = 1, column = 0)
number3 = Label(main, text="Number 3").grid(row = 2, column = 0)
entry1  = Entry(main, textvariable=entry1var).grid(row=0,column=1)
entry2  = Entry(main, textvariable=entry2var).grid(row=1,column=1)
entry3  = Entry(main, textvariable=entry3var).grid(row=2,column=1)
button1 = Button(main, text="Try Number",command=check1).grid(row=0,column=2)
button2 = Button(main, text="Try Number").grid(row=1,column=2)
button3 = Button(main, text="Try Number").grid(row=2,column=2)

labelent1 = Label(main, text="Waiting for Input").grid(row = 0, column = 3)
labelent2 = Label(main, text="Waiting for Input").grid(row = 1, column = 3)
labelent3 = Label(main, text="Waiting for Input").grid(row = 2, column = 3)



mastercodelabel= Label(main, text="Enter master code below:").grid(row=3,column=1)
mastercodeentry= Entry(main).grid(row=4,column=1)
mastercodebutton= Button(main,text="Enter").grid(row=4,column=2)




#main.config(menu=menubar)
main.mainloop()




And this is the error displayed when clicking on button1:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python33\lib\tkinter\__init__.py", line 1475, in __call__
    return self.func(*args)
  File "C:/Users/User/Desktop/Programming/Tkinter/Tkinter.py", line 15, in check1
    labelent1.destroy()
UnboundLocalError: local variable 'labelent1' referenced before assignment


Thanks, Lewis.

[toc] | [next] | [standalone]


#63855

FromLewis Wood <fluttershy363@gmail.com>
Date2014-01-13 10:51 -0800
Message-ID<7b21d69d-7272-4e7b-ab85-621f044d205c@googlegroups.com>
In reply to#63854
Forgot to mention I am using Python 3.3.3

[toc] | [prev] | [next] | [standalone]


#63856

FromChristian Gollwitzer <auriocus@gmx.de>
Date2014-01-13 20:03 +0100
Message-ID<lb1dae$tbm$1@dont-email.me>
In reply to#63854
Am 13.01.14 19:49, schrieb fluttershy363@gmail.com:
>
> Inside the function is where I am having the problem, I am trying to get it to delete the label so that it may then replace it with a shorter text.
> Here is the full code:
>
>
>
>
> from tkinter import *
> import random
> main = Tk()
> main.title("Crack the Code")
>
> def check1():
>      entry = entry1var.get()
>      if entry == num1:
>          labelent1.destroy()
>          labelent1 = Label(main, text="Correct!",fg="green").grid(row = 0, column = 3)

This is the wrong way to do it. Yes, in principle you could remove the 
label and put a new one there; but it's much better to just change the 
text of it by means of either

	labelent1.configure(text="New text ")

or by linking a variable with the label variable at the setup time
	somestringvar = StringVar("initial text")
	Label(main, textvariable=somestringvar)

and then change that variable
	somestringvar.set("New text")

Both of these don't solve the error, though; it has nothing to do with 
Tk, you just did not make labelent1 global. However, I strongly advise 
to use an object for the entire window, where you make this labelent1 an 
instance variable (put into self).

	Christian

[toc] | [prev] | [next] | [standalone]


#63857

FromLewis Wood <fluttershy363@gmail.com>
Date2014-01-13 11:21 -0800
Message-ID<acc5ef7f-a408-42ca-9b67-c94950cfe571@googlegroups.com>
In reply to#63856
When I try to use the labelent1.configure, it greets me with an error:
AttributeError: 'NoneType' object has no attribute 'configure'

I changed the labelent's to global. Don't suppose you know why?
Also how would I go about using an object for the entire window. I am still a Novice at Tkinter and Python but can make my way around it.

[toc] | [prev] | [next] | [standalone]


#63858

FromPeter Otten <__peter__@web.de>
Date2014-01-13 20:36 +0100
Message-ID<mailman.5426.1389641835.18130.python-list@python.org>
In reply to#63854
fluttershy363@gmail.com wrote:

> Inside the function is where I am having the problem, I am trying to get
> it to delete the label so that it may then replace it with a shorter text.
> Here is the full code:

> def check1():
>     entry = entry1var.get()
>     if entry == num1:
>         labelent1.destroy()
>         labelent1 = Label(main, text="Correct!",fg="green").grid(row = 0,
>         column = 3)
>     elif entry > num1:
>         labelent1.destroy()
>         labelent1 = Label(main, text="Too Big",fg="red").grid(row = 0,
>         column = 3)
>     elif entry < num1:
>         labelent1.destroy()
>         labelent1 = Label(main, text="Too Small",fg="red").grid(row = 0,
>         column = 3)

> And this is the error displayed when clicking on button1:
> 
> Exception in Tkinter callback
> Traceback (most recent call last):
>   File "C:\Python33\lib\tkinter\__init__.py", line 1475, in __call__
>     return self.func(*args)
>   File "C:/Users/User/Desktop/Programming/Tkinter/Tkinter.py", line 15, in
>   check1
>     labelent1.destroy()
> UnboundLocalError: local variable 'labelent1' referenced before assignment
> 
> 
> Thanks, Lewis.

Kudos, your problem description is very clear!

Your post would be perfect, had you reduced the number of Labels from three 
to one ;)

The error you are seeing has nothing to do with the GUI. When you assign to 
a name inside a function Python determines that the name is local to that 
function. A minimal example that produces the same error is

>>> a = "global"
>>> def test():
...     print(a)
...     a = "local"
... 
>>> test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in test
UnboundLocalError: local variable 'a' referenced before assignment

The name `a` passed to print() references the local `a` which is not yet 
defined. A possible fix is to tell Python to reference the global `a`

>>> a = "global"
>>> def test():
...     global a
...     print(a)
...     a = "local"
... 
>>> test()
global
>>> a
'local'

However, in the case of your GUI code you should not destroy and create 
Label instances -- it is more efficient (and easier I think) to modify the 
Label's text:

(1) working demo with 'global' -- don't do it that way:

from tkinter import *

main = Tk()

def check1():
    global labelent1
    labelent1.destroy()
    labelent1 = Label(main, text="Correct!", fg="green")
    labelent1.grid(row = 0, column = 3) # must be a separate statement as
                                        # grid() returns None

Button(main, text="Try Number", command=check1).grid(row=0, column=2)
labelent1 = Label(main, text="Waiting for Input")
labelent1.grid(row=0, column=3) # must be a separate statement as 
                                # grid() returns None

main.mainloop()


(2) The way to go, modify the label text instead of replacing it:

from tkinter import *

main = Tk()

def check1():
    labelent1.configure(text="Correct!", fg="green")

Button(main, text="Try Number", command=check1).grid(row=0, column=2)
labelent1 = Label(main, text="Waiting for Input")
labelent1.grid(row=0, column=3)

main.mainloop()

> global num1

By the way, global declarations on the module level have no effect.

[toc] | [prev] | [next] | [standalone]


#63868

FromDennis Lee Bieber <wlfraed@ix.netcom.com>
Date2014-01-13 20:39 -0500
Message-ID<mailman.5434.1389663555.18130.python-list@python.org>
In reply to#63854
On Mon, 13 Jan 2014 10:49:07 -0800 (PST), fluttershy363@gmail.com declaimed
the following:

>
>Inside the function is where I am having the problem, I am trying to get it to delete the label so that it may then replace it with a shorter text.
>Here is the full code:
>
	<snip>
>
>global num1
>global num2
>global num3

	These do not do what you think they do...

	"global" is used INSIDE of functions (def) to specify that references
to the name on the inside MUST access the module level name.

	Note: read-only access does not need "global"; only bindings to the
name (assignments) have to have the "global" otherwise they define a local
name.
-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
    wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/

[toc] | [prev] | [next] | [standalone]


#63869

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2014-01-13 18:47 -0800
Message-ID<e8e5c10d-67c8-49ed-a9ce-f6dbb177039b@googlegroups.com>
In reply to#63854
On Monday, January 13, 2014 12:49:07 PM UTC-6, Lewis Wood wrote:
> labelent1 = Label(main, text="Correct!",fg="green").grid(row = 0, column = 3)
> 
> [snip]
> 
> UnboundLocalError: local variable 'labelent1' referenced before assignment

Observe the following interactive session and prepare to be enlightened.

## INCORRECT ##
py> from Tkinter import *
py> root = Tk()
py> label = Label(root, text="Blah").pack()
py> type(label)
<type 'NoneType'>

## CORRECT ##
py> label = Label(root, text="Blah")
py> label.pack()
py> label
<Tkinter.Label instance at 0x027C69B8>
py> type(label)
<type 'instance'>

## ANY QUESTIONS? ##
py> help()

[toc] | [prev] | [next] | [standalone]


#63870

FromChris Angelico <rosuav@gmail.com>
Date2014-01-14 14:12 +1100
Message-ID<mailman.5435.1389669132.18130.python-list@python.org>
In reply to#63854
On Tue, Jan 14, 2014 at 5:49 AM,  <fluttershy363@gmail.com> wrote:
>     entry = entry1var.get()
>     if entry == num1:
>     elif entry > num1:
>     elif entry < num1:
>
> num1 =str(random.randint(10,99))
> num2 =str(random.randint(10,99))
> num3 =str(random.randint(10,99))
> mastercode = num1+num2+num3

Be careful of code like this. You've specified that your three parts
range from 10 through 99, so this will work as long as the user knows
this and enters exactly two digits. Doing inequality comparisons on
strings that represent numbers will work as long as they're the same
length, but if the lengths vary, the string comparisons will start at
the beginning - not what most people will expect. These are all true:

"2" > "10"
"3.14159" > "2,000,000"
"42" < "Life, the universe, and everything"
"00012" < "12"

If your intention is to have a six-digit number, you could simply ask
for one, and then format the pieces accordingly:

num = random.randint(1,999999)
num_str = "%06d" % num

You can then slice up num_str as needed (it'll have leading zeroes if
it needs them), or you can do numerical comparisons against num
itself.

ChrisA

[toc] | [prev] | [next] | [standalone]


#63925

FromLewis Wood <fluttershy363@gmail.com>
Date2014-01-14 11:11 -0800
Message-ID<3f7e442e-b86d-45c9-bd70-52c6abcca549@googlegroups.com>
In reply to#63870
I cannot say how grateful I am to find such a community willing to help <3 Thanks to everyone posting, learned a lot of new stuff :) Never knew you could just bring a local var into a def block using global inside of the function. Again, thanks for taking your time to help out newbies to programming such as myself.

[toc] | [prev] | [next] | [standalone]


#63944

FromLewis Wood <fluttershy363@gmail.com>
Date2014-01-14 13:27 -0800
Message-ID<95e61d6c-5626-4d29-9dda-98e1bcb38546@googlegroups.com>
In reply to#63925
Also anyone know how to create an entry box for Tkinter where you can only enter in 2 digits?

[toc] | [prev] | [next] | [standalone]


#63947

FromChristian Gollwitzer <auriocus@gmx.de>
Date2014-01-14 22:33 +0100
Message-ID<lb4afa$4dp$1@dont-email.me>
In reply to#63944
Am 14.01.14 22:27, schrieb Lewis Wood:
> Also anyone know how to create an entry box for Tkinter where you can only enter in 2 digits?
>
You must use a validator to achieve this. This is a more advanced topic 
though. A validator is a function that is called whenever the user keys 
something in - even by copy/pasting - and has to decide, whether this 
change is accepted or not. It is relatively easy to annoy your users if 
the validator is not written carefully. For instance, you must always 
accept th eempty string, otherwise the users won't be able to delete 
everything - very annoying behaviour.

See for example this SO question

http://stackoverflow.com/questions/4140437/python-tkinter-interactively-validating-entry-widget-content

	Christian

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web