'What causes Attribute Error: 'classObject' object has no attribute '_w'?

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!



Solution 1:[1]

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')

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mote Zart