To the good people on comp.lang.python:
I have the following Tkinter class (python 2.7.3):
from Tkinter import *
class ScrolledCanvas(Frame):
def __init__(self, master, width, height, bg, cursor):
Frame.__init__(self, master)
self.__nonzero__ = lambda: True
canv = self.canvas = Canvas(self, bg=bg, relief=SUNKEN)
# self.__getattr__ = lambda x, name: getattr(self.canvas, name)
canv.config(width=width, height=height) # display area size
canv.config(scrollregion=(0, 0, width, height)) # canvas size corners
canv.config(highlightthickness=0) # no pixels to border
ybar = Scrollbar(self)
ybar.config(command=canv.yview) # xlink sbar and canv
canv.config(yscrollcommand=ybar.set) # move one moves other
xbar = Scrollbar(self)
xbar.config(command=canv.xview) # xlink sbar and canv
canv.config(xscrollcommand=xbar.set) # move one moves other
canv.grid(row = 0, column = 0, sticky = 'news')
ybar.grid(row = 0, column = 1, sticky = 'ns')
xbar.grid(row = 1, column = 0, sticky = 'ew')
self.rowconfigure(0, weight = 1)
self.columnconfigure(0, weight = 1)
self.create_text(20, 20, text = 'Did it!', fill = 'red')
def __getattr__(self, name):
return getattr(self.canvas, name)
root = Tk()
app = ScrolledCanvas(root, 400, 300, 'white', 'hand2')
app.pack()
root.mainloop()
I just added the __getattr__ method, and the program crashed in the Canvas
constructor. There is apparently a call to self.__nonzero__ somewhere in
Tkinter.py, and since the constructor hasn't exited yet, sel.fcanvas isn't
defined yet, so __getattr__ recurses indefinitely.
I fixed this as you see, by defining self.__nonzero__ before the call to the
constructor. Now, I have two questions:
1. I originally defined self.__nonzero__ = lambda x: True, on the assumption
that when self.__nonzero__ was called, the interpreter would pass self as an
argument. Wrong. No arguments were passed. Why is this?
2. I find this solution rather unsatisfactory, since there's a rather obscure
line of code here. I tried eliminating the def of __gertattr__ and the
definition of self.__nonzero__ and adding this line after the constructor:
self.__getattr__= lambda name: getattr(self.canvas, name)
This get through the constructor all right, but crashes with the message that a
ScrolledCanvas object has no create_text attribute. (I've tried passing two
arguments to the lambda, but it makes no difference.)
I don't understand what's going on at all. Can't I dynamically define
__getattr__? How should I go about it? By the way, another thing that didn't
work was calling the method delegate instead of __getattr__. Then after the
constructor call, I wrote
self.__getattr__ = self.delegate. This crashed as before on self.create_text.
I just tried a little experiment with __add__ and had no success, so I guess my
problem is with overloaded operators in general.
I'd really appreciate an explanation, or a pointer to relevant documentation.
--
http://mail.python.org/mailman/listinfo/python-list