Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > TK program problem

Reply
Thread Tools

TK program problem

 
 
bvdp
Guest
Posts: n/a
 
      05-20-2011
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!

 
Reply With Quote
 
 
 
 
Ian Kelly
Guest
Posts: n/a
 
      05-20-2011
On Fri, May 20, 2011 at 12:03 PM, bvdp <(E-Mail Removed)> wrote:
> 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.


I'm not a tk user, but it sounds like it has regressed from accepting
arbitrary callables as callbacks to accepting functions specifically.

What happens if you replace:

("Favorites", selectFav),

with:

("Favorites", lambda: selectFav()),
 
Reply With Quote
 
 
 
 
bvdp
Guest
Posts: n/a
 
      05-20-2011

> I'm not a tk user, but it sounds like it has regressed from accepting
> arbitrary callables as callbacks to accepting functions specifically.
>
> What happens if you replace:
>
> ("Favorites", selectFav),
>
> with:
>
> ("Favorites", lambda: selectFav()),


Okay, this works. Great and thanks! Seems to me that the way I was
doing it should be alright ... and I've got some other programs
exhibiting the same problem.

Before I go "fixing" the issue ... is this known or even a bug?
 
Reply With Quote
 
Ian Kelly
Guest
Posts: n/a
 
      05-20-2011
On Fri, May 20, 2011 at 4:12 PM, bvdp <(E-Mail Removed)> wrote:
> Okay, this works. Great and thanks! Seems to me that the way I was
> doing it should be alright ... and I've got some other programs
> exhibiting the same problem.
>
> Before I go "fixing" the issue ... is this known or even a bug?


The docs [1] say that a callback is a function, so I guess that if it
worked before it was just luck. You should bring it up on the tkinter
list and see what they have to say about it, though.

I'm a bit confused about why you would want to use a class as a
callback anyway. It looks like when the button is clicked it
instantiates the class and then throws it away?

[1] http://docs.python.org/library/tkint...ion-data-types
 
Reply With Quote
 
bvdp
Guest
Posts: n/a
 
      05-20-2011
Probably the fix is to use a function

> The docs [1] say that a callback is a function, so I guess that if it
> worked before it was just luck. *You should bring it up on the tkinter
> list and see what they have to say about it, though.
>
> I'm a bit confused about why you would want to use a class as a
> callback anyway. *It looks like when the button is clicked it
> instantiates the class and then throws it away?


I have no idea why I used a class like this, expect that it seemed to
work at the time. Yes, the class is instantiated when the button is
clicked. Then, the user stays in the class and uses its methods until
he hits <close> in the class.

So, I guess what's happening is that I'm treating the button click
much like a call to a new program/window which sets some options, etc.
in the main program.

You mention the tkinter group. Ummm, what group is that???

Best,
 
Reply With Quote
 
Ian Kelly
Guest
Posts: n/a
 
      05-20-2011
On Fri, May 20, 2011 at 5:07 PM, bvdp <(E-Mail Removed)> wrote:
> You mention the tkinter group. Ummm, what group is that???


http://tkinter.unpythonic.net/wiki/TkinterDiscuss
 
Reply With Quote
 
bvdp
Guest
Posts: n/a
 
      05-20-2011
On May 20, 4:29*pm, Ian Kelly <(E-Mail Removed)> wrote:
> On Fri, May 20, 2011 at 5:07 PM, bvdp <(E-Mail Removed)> wrote:
> > You mention the tkinter group. Ummm, what group is that???

>
> http://tkinter.unpythonic.net/wiki/TkinterDiscuss


Thanks. New one for me. I'll subscribe and see if they know about
this.

Best,
 
Reply With Quote
 
rantingrick
Guest
Posts: n/a
 
      05-20-2011
On May 20, 6:07*pm, bvdp <(E-Mail Removed)> wrote:
> Probably the fix is to use a function
>
> > The docs [1] say that a callback is a function, so I guess that if it
> > worked before it was just luck. *You should bring it up on the tkinter
> > list and see what they have to say about it, though.

>
> > I'm a bit confused about why you would want to use a class as a
> > callback anyway. *It looks like when the button is clicked it
> > instantiates the class and then throws it away?

>
> I have no idea why I used a class like this, expect that it seemed to
> work at the time. Yes, the class is instantiated when the button is
> clicked. Then, the user stays in the class and uses its methods until
> he hits <close> in the class.


Thats sounds to me a lot like hammering square pegs though round
holes... Perhaps you should explain first in "plain english" what
problem your application is intended to solve, then how it is expected
to interact with the user, and finally, what exactly is NOT working
correctly. I would suffix such a documentary with the current source
code, verbatim.

 
Reply With Quote
 
Peter Otten
Guest
Posts: n/a
 
      05-21-2011
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 <module>
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.

 
Reply With Quote
 
bvdp
Guest
Posts: n/a
 
      05-22-2011
Thanks, Peter, for the detailed explanation. I was going to write a
bit of sample/minimal code to demo this, but you nicely beat me to
it!

> 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 <module>
> * * 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"
> $


Any idea why I'm not getting any traceback in my program? It just runs
and appears to ignore the callback.

> 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.


Yes, I can confirm that both the lambda and setting the class to:

class selectFav(object):

works.

> 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.


IIRC, I used the class method since it nicely encapsulates a set of
operations:

- create/raise a window
- list a set of configurable options
- have <cancel> and <save> buttons, both of which destroy the
window.

Having a function as the callback certainly works as well. Not sure
which is the best method in the long run ... I'm trying to use classes
more in my programming since it's nice to wrap a bunch of functions up
like this.

Thanks again.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Problem with a JAVA program launched in a PHP program sylsau Java 1 04-29-2006 09:53 PM
System program/ Application program ?? Parvsandhu Java 2 07-11-2005 09:08 AM
how to convert a java program to an exe program ola Java 3 02-16-2004 09:42 AM
Calling Java program in another Java program Rey Java 4 12-12-2003 10:18 PM
passing data between Java program and C program--help pipi Java 1 07-21-2003 05:02 AM



Advertisments