I'm working with tkinter in python and I have an annoying bug that I can't seem to fix, although the answer is probably obvious.
I am trying to call a dictionary with a string, but for some reason I get the error:
Type Error: unhashable type: StringVar. Here is a snippet of code with that issue:
from Tkinter import *
gpa = Tk()
weightsy = {'0': 2, '.1': 6, '.25':.2, '.5':.56, '.75':75, '1':12}
acadw = StringVar()
acadw.set(".1")
print (weightsy.get(acadw)) #Here is the issue; it should return the integer 6.
mainloop()
For extra info, if I remove the tkinter related code (such as the import, gpa = Tk(), StringVar, .set, mainloop()) it works, so I believe it is a tkinter related issue.
Just as you had to call set method of StringVar object, you also need to call get to retrieve the str data.
print weightsy[acadw.get()]
The dictionary doesn't know to convert your object into a string so it attempts to get the value associated with acadw. You get a TypeError rather than a KeyError since StringVar objects happen to be unhashable.
Related
I'm working on a project where you click a button and it changes an int and writes it to the screen. My issues is that when I try to set a new value to the int it comes back with an AttributeError.
def busy():
unit_status.set(7)
Everything else is working except for that one line, and I can't for the life of me figure out why.
While this thread is a bit old, I dont think LouieC's response fully answered the OP's concern.
LouieC mentions that set is a built-in class, which is correct. But it is likely Warrior's Path was looking for the values, since he wanted to write them to the screen.
IF he didnt ask, then I am asking based upon an observation in the following code, adapted from the geeksforgeeks.org explanation. My point is addressed in the comments, particularly at the end.
Notice when LouieC's technique is applied it seems to incorrectly overwrite the entirety of IntVar.
# importing tkinter module
from tkinter import *
# creating Tk() variable
# required by Tkinter classes
master = Tk()
# Tkinter variables
# initialization using constructor
intvar = IntVar(master, value = 25, name ="2")
strvar = StringVar(master, "Hello !")
boolvar = BooleanVar(master, True)
doublevar = DoubleVar(master, 10.25)
print(intvar) # This prints the NAME, not the value.... the name is auto-assigned by python
print(strvar) # if not explicity declared...
print(boolvar)
print(doublevar)
print(intvar.get()) # This prints the VALUE, not the name....
print(strvar.get())
print(boolvar.get())
print(doublevar.get())
# But now watch what happens...
intvar = 1
print(intvar)
print(intvar.get())
# What's interesting here is... print(intvar.get()) worked at line 20...
and yet now it generates the following error
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-16-61984dfda0fb> in <module>
26 intvar = 1
27 print(intvar)
---> 28 print(intvar.get())
AttributeError: 'int' object has no attribute 'get'
If one runs a type test, in the first case, around line 20:
print(type(intvar))
One will get:
<class 'tkinter.IntVar'>
But if one runs the same type test after LouieC's reassignment, one will get:
<class 'int'>
That's why I said the reassignment doesnt work right.
The OP's question still seems to be open.
This is not how you reassign a variable of type integer; you want:
unit_status = 7
set is a built-in class in Python; official docs here
A set object is an unordered collection of distinct hashable objects. Common uses include membership testing, removing duplicates from a sequence, and computing mathematical operations such as intersection, union, difference, and symmetric difference. (For other containers see the built-in dict, list, and tuple classes, and the collections module.)
I've created a toplevel window in my Tkinter program. However it just doesn't seem to get the geometry part.
Some of the code:
def calreco():
calreco_screen = Toplevel(cc)
calreco_screen.title("Your Recommended Calorie Intake Is")
calreco.geometry("400x400")
You are initiated and called a different/unknown object.
calreco.geometry("400x400")
Instead, Try
calreco_screen.geometry("400x400")
This could solve your issue.
I'm trying to run a function called password() with argument "t" on pressing a button in Tkinter.
Problem is that this gives me a TypeError even though the code seems alright.
self.Button5.configure(command=lambda t='restart': password(t))
Error:
TypeError: 'str' object is not callable
(here is a link to whole code if necessary, error is on line 372: https://codeshare.io/G8VW6A)
In line 103 of your code you create global variable 'password', which has the same name as your function. Just change the variable names so they don't clash.
I am using Wing to write and debug a Tkinter GUI. I am finding that the Stack Data View doesn't seem to match the actual attributes of my widgets. Take this code for example:
import Tkinter
import ttk
root = Tkinter.Tk()
checkbutton = ttk.Checkbutton(root, text="Test Check Button")
print checkbutton.text
This gives me an attribute error at the last line. However, when I look at the stack, there is clearly an attribute called 'text' with the value that I'm looking for:
Anyone know what's going on?
I'm using:
Wing version: Wing IDE Pro 5.1.3-1 (rev 33002)
Tkinter version: '$Revision: 81008 $'
Python version: 2.7.10
I posted this to the Wing email list, and I got the following response from the developers:
It looks like a ttk.Checkbutton defines keys() and __getitem__()
methods to exposes tk attributes via checkbutton[<name>]. Because
of the keys() and __getitem__(), Wing is displaying the instance
as if it were a dictionary, with the keys and values interspersed with
the attributes. Wing does this because often you want to view an
object that defines keys() and __getitem__() as if it were a
dictionary, but I agree that it's confusing in this instance.
We'll try to improve this in a future release.
What you are calling attributes are not object attributes. Widgets use an internal system for managing the widget options. .text is not an attribute, which is why you get the error. To reference the configuration use .cget(...) to get the value and .configure(...) to change the value.
UPDATED: SEE BELOW
I've been porting the code for this assignment: http://www.stanford.edu/class/cs221/progAssignments/PA1/search.html (the entire source code is available as zip from there)
from Python 2.x to 3.x. Note, porting is not the assignment, that's just me trying to keep the code up to date and avoiding installing another version of Python...
After the usual 2.x -> 3.x syntax fixes (printing, exception raising, etc), and realizing that the module Tkinter is now known as tkinter in 3.x (lower-case), I've run into stranger problems, with this snippet and several others like it:
def keys_pressed(d_o_e=tkinter.tkinter.dooneevent,d_w=tkinter.tkinter.DONT_WAIT)
The errors are of the type:
AttributeError: 'module' object has no attribute 'tkinter'
Code completion in my IDE and the variable trace indeed seems to indicate that the tkinter module has no attribute or sub-class tkinter under which one might refer to dooneevent or DONT_WAIT. However, there are a few other references on the Internet of people using constructs like
_tkinter.dooneevent(_tkinter.DONT_WAIT)
to move the main loop ahead, but even referencing it like that still yields the same error.
Any ideas greatly appreciated.
UPDATE: Referring to the _root_window via lambda notation seems to work, as in it no longer complains pre-execution time in the majority of cases. To my untrained eye however, this is basically "magic", and as such I have little idea what this subsequent error is saying or how to work around it. The method now looks like this, with my changes in the first line:
def move_to(object, x, y=None, d_o_e=lambda arg: _root_window(arg), d_w=tkinter._tkinter.DONT_WAIT):
if y is None:
try: x, y = x
except: raise 'incomprehensible coordinates'
horiz = True
newCoords = []
current_x, current_y = _canvas.coords(object)[0:2] # first point
for coord in _canvas.coords(object):
if horiz:
inc = x - current_x
else:
inc = y - current_y
horiz = not horiz
newCoords.append(coord + inc)
_canvas.coords(object, *newCoords)
d_o_e(d_w)
and the error I get is:
TypeError: 'Tk' object is not callable
referencing the line where the method is defined (first line above).
It appears Tkinter.tkinter was changed to tkinter._tkinter in Python 3. Compare these docs from Python 2 with these from Python 3. Also, dooneevent is no longer in tkinter._tkinter, but is still a member of the Tk (aka root) object.
So change your code to
def keys_pressed(d_o_e=lambda arg: _root_window.dooneevent(arg),
d_w=tkinter._tkinter.DONT_WAIT):
This takes advantage of the fact that in your linked code _root_window is global, so while _root_window is not available when the class is defined, it will be available when the lambda is run.