Path: csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!news.albasani.net!weretis.net!feeder1.news.weretis.net!news.solani.org!.POSTED!not-for-mail From: Peter Otten <__peter__@web.de> Newsgroups: comp.lang.python Subject: Re: TK program problem Followup-To: comp.lang.python Date: Sat, 21 May 2011 10:18:59 +0200 Organization: None Lines: 109 Message-ID: References: <9f91909a-ce08-47dd-81d3-e7cf2edad3b6@h12g2000pro.googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7Bit X-Trace: solani.org 1305965931 13736 eJwNycEBwCAIA8CVUJJgx5EC+4/Q3vfoWnoDosDh1C2/aJ5uVAe5/1hhIGUTlWbp56l2E3LvDx5NEJw= (21 May 2011 08:18:51 GMT) X-Complaints-To: abuse@news.solani.org NNTP-Posting-Date: Sat, 21 May 2011 08:18:51 +0000 (UTC) X-User-ID: eJwFwQkBwDAIA0BL5QurHAjFv4TdhUHAdAQ8Nja7s+ijDP8es0Uvjnq9nECPtQ0eFVmvrraJkL3skSPr/gNuwBZn Cancel-Lock: sha1:uPHYyrKYW7e3ijkJs72aTJe7agc= X-NNTP-Posting-Host: eJwNysEVADEEBcCWWHyUg0T/JWyu88YEjHGFQW1t3XQ0OT3z6felF+dCZuPo4e0LmztBe1q4tHgRof4abUdfqpQGmjWGmn+9wRnV Xref: x330-a1.tempe.blueboxinc.net comp.lang.python:5905 bvdp wrote: > I've just done an update to my system here to Ubuntu 11.04. Mostly no > problems ... but I have an important (to me) python/TK program that's > stopped working. Well, it works ... mostly. > > The python version is 2.7.1+ (no idea what the + means!). > > I _think_ I have traced the problem to certain menus which call a > class. The calls appear to be ignored. > > Basically, what I have is a line like: > > bf = makeButtonBar(root, row=0, column=0, buttons=( > ("Quit", self.quitall ), > ("Stop", self.stopPmidi ), > ("New Dir", self.chd), > ("Load Playlist", self.playList), > ("Favorites", selectFav), > ("Options", setOptions) ) ) > > To create a menu bar. The function makeButtonBar() creates the buttons > with: > > for txt, cmd in buttons: > Button(bf, text=txt, height=1, command=cmd).grid(column=c, > row=0, pady=5) > > > All this is fine (and worked perfectly before my upgrade). The menu > items which are ordinary functions continue to work. BUT the callbacks > which are classes are just ignored when they are clicked. > > A cut from one of the ignored classes: > > > class selectFav: > > def __init__(self): > ... > > And I've inserted some prints in the __init__() and nothing is > printed. Also, converted the class to new-style () but no change there > either. > > Either python/tk has changed or my system is totally $*(#*#. > Suggestions welcome! Here's a minimal script to reproduces the problem: $ cat tkcallclass.py import Tkinter as tk root = tk.Tk() root.withdraw() class Classic: def __init__(self): print "hello" button = tk.Button(root, command=Classic) button.invoke() $ python2.6 tkcallclass.py hello $ python2.7 tkcallclass.py Traceback (most recent call last): File "tkcallclass.py", line 11, in button.invoke() File "/usr/local/lib/python2.7/lib-tk/Tkinter.py", line 2081, in invoke return self.tk.call(self._w, 'invoke') _tkinter.TclError: invalid command name "__main__.Classic" $ In 2.7 the Tkinter code was changed to use hasattr(obj, "__call__") instead of callable(obj) to recognize callbacks. This gives different results for oldstyle classes >>> class A: pass ... >>> callable(A) True >>> hasattr(A, "__call__") False ...and they are no longer registered automatically with Tkinter. In theory you could register them explicitly yourself $ cat tkcallclass2.py import Tkinter as tk root = tk.Tk() root.withdraw() class Classic: def __init__(self): print "hello" button = tk.Button(root, command=root.register(Classic)) button.invoke() $ python2.7 tkcallclass2.py hello but in practice changing them to newstyle (i. e. have them inherit from object) or wrapping them in a lambda appears convenient. Personally, I would reconsider whether using a class as a callback is really necessary. Replacing the class with a function should be a straightforward process.