Reputation: 138
I'm working with Python 3.1, and I want to create a game. I made a class Board(Canvas):
Why? because I need to keep track of the pieces via 'tag'. BUT, when I attempt to bind a tag to a piece, I get a traceback that read something like...
Traceback (most recent call last):
File "/Users/bluedragon1223/Desktop/Djambi0-2.py", line 282, in <module>
x = Board()
File "/Users/bluedragon1223/Desktop/Djambi0-2.py", line 94, in __init__
self.tag_bind(self.canM, '<1>', _onPieceClick)
File "/Library/Frameworks/Python.framework/Versions/3.1/lib/python3.1/tkinter/__init__.py",
line 2103, in tag_bind
return self._bind((self._w, 'bind', tagOrId),
AttributeError: 'Board' object has no attribute '_w'
I can follow the code all the way to the error, and I think I lack the understanding of what '_w' is here.
After x = Board()
the def __init__(self, window=mainWin):
contains self.M = PhotoImage(file=path+'M.gif')
. self.M
then goes into:
def __draw(self):
canvas = Canvas(mainWin,width=810,height=810)
for i in range(9):
canvas.create_line(90*i,0,90*i,810)
for j in range(9):
canvas.create_line(0,90*j,810,90*j)
canvas.create_rectangle(3,810,810,3)
canvas.bind('<1>', _point2square)
canvas.pack()
self.canM = canvas.create_image(405,405,image=self.M,tag = 'M')
After that, it's used in self.tag_bind(self.canM, '<1>', _onPieceClick)
. And that's where the error occurs. My question is why? What did I do, and how do I fix it?
I appreciate any sort of help!
Upvotes: 3
Views: 6803
Reputation: 960
I continually run into this error as a TKinter beginner so here is a how-I-fixed-the-error rather an explanation of its origins, as per OP.
Binding with a lambda, I passed in a function declaration rather than calling the function.
layout.bind("<Return>",lambda event: self.handleInput)
AttributeError: 'layout' object has no attribute '_w'
Adding a manual function call made it work w.o error.
layout.bind("<Return>",lambda event: self.handleInput())
Removing the lambda allowed the function to fire as expected using only the declaration, but then there was a different error.
layout.bind("<Return>",self.handleInput)
handleInput() takes 1 positional argument but 2 were given
To solve this is I added a second param to handleInput
. This does add an unused param, maybe, but it gets rid of the error.
def handleInput(self,event):
print('works')
Upvotes: 1
Reputation: 385970
A tkinter object such as a canvas is simply a proxy object for an actual tk widget. The attribute _w
contains the internal name of the real tk widget. For example:
$ python2.5
Python 2.5.4 (r254:67917, Dec 23 2008, 14:57:27)
[GCC 4.0.1 (Apple Computer, Inc. build 5363)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import Tkinter as tk
>>> root=tk.Tk()
>>> canvas = tk.Canvas(root)
>>>> print canvas._w
.8327736
If you get an error like object has no attribute '_w'
it means that somehow you created an instance of an object that thinks it is a tk widget (and thus has methods like tag_bind
), but doesn't actually have a tk widget associated with it.
One way this can happen is if you subclass a tkinter widget but don't call the __init__
method of the parent class. For example, you get get a similar error doing this (notice how I don't call __init__
on the Canvas
class):
>>> class Board(tk.Canvas):
... def __init__(self, *args):
... pass
...
>>> board = Board()
>>> board.tag_bind("whatever","<1>", None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/lib-tk
/Tkinter.py", line 2129, in tag_bind
return self._bind((self._w, 'bind', tagOrId),
AttributeError: Board instance has no attribute '_w'
My guess is that you're doing something like this. You're defining Board as a subclass of Canvas
but you aren't calling the Canvas.__init__
method (or are calling it and ignoring any errors it throws)
Upvotes: 4