Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #5867 > unrolled thread
| Started by | bvdp <bob@mellowood.ca> |
|---|---|
| First post | 2011-05-20 11:03 -0700 |
| Last post | 2011-05-23 00:25 +1000 |
| Articles | 16 — 6 participants |
Back to article view | Back to comp.lang.python
TK program problem bvdp <bob@mellowood.ca> - 2011-05-20 11:03 -0700
Re: TK program problem Ian Kelly <ian.g.kelly@gmail.com> - 2011-05-20 13:20 -0600
Re: TK program problem bvdp <bob@mellowood.ca> - 2011-05-20 15:12 -0700
Re: TK program problem Ian Kelly <ian.g.kelly@gmail.com> - 2011-05-20 16:33 -0600
Re: TK program problem bvdp <bob@mellowood.ca> - 2011-05-20 16:07 -0700
Re: TK program problem Ian Kelly <ian.g.kelly@gmail.com> - 2011-05-20 17:29 -0600
Re: TK program problem bvdp <bob@mellowood.ca> - 2011-05-20 16:34 -0700
Re: TK program problem rantingrick <rantingrick@gmail.com> - 2011-05-20 16:37 -0700
Re: TK program problem bvdp <bob@mellowood.ca> - 2011-05-21 17:07 -0700
Re: TK program problem Peter Otten <__peter__@web.de> - 2011-05-21 10:18 +0200
Re: TK program problem bvdp <bob@mellowood.ca> - 2011-05-21 17:03 -0700
Re: TK program problem Terry Reedy <tjreedy@udel.edu> - 2011-05-21 20:33 -0400
Re: TK program problem bvdp <bob@mellowood.ca> - 2011-05-21 19:20 -0700
Re: TK program problem Terry Reedy <tjreedy@udel.edu> - 2011-05-22 17:17 -0400
Re: TK program problem rantingrick <rantingrick@gmail.com> - 2011-05-22 07:03 -0700
Re: TK program problem Chris Angelico <rosuav@gmail.com> - 2011-05-23 00:25 +1000
| From | bvdp <bob@mellowood.ca> |
|---|---|
| Date | 2011-05-20 11:03 -0700 |
| Subject | TK program problem |
| Message-ID | <9f91909a-ce08-47dd-81d3-e7cf2edad3b6@h12g2000pro.googlegroups.com> |
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!
[toc] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2011-05-20 13:20 -0600 |
| Message-ID | <mailman.1857.1305919249.9059.python-list@python.org> |
| In reply to | #5867 |
On Fri, May 20, 2011 at 12:03 PM, bvdp <bob@mellowood.ca> 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()),
[toc] | [prev] | [next] | [standalone]
| From | bvdp <bob@mellowood.ca> |
|---|---|
| Date | 2011-05-20 15:12 -0700 |
| Message-ID | <10f0acf7-b63b-4cf3-949b-5d0caba19fb0@z13g2000prk.googlegroups.com> |
| In reply to | #5874 |
> 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?
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2011-05-20 16:33 -0600 |
| Message-ID | <mailman.1864.1305930866.9059.python-list@python.org> |
| In reply to | #5885 |
On Fri, May 20, 2011 at 4:12 PM, bvdp <bob@mellowood.ca> 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/tkinter.html#tk-option-data-types
[toc] | [prev] | [next] | [standalone]
| From | bvdp <bob@mellowood.ca> |
|---|---|
| Date | 2011-05-20 16:07 -0700 |
| Message-ID | <a20a9805-5f61-4112-a5b2-a7685eea7063@18g2000prd.googlegroups.com> |
| In reply to | #5886 |
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,
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2011-05-20 17:29 -0600 |
| Message-ID | <mailman.1867.1305934179.9059.python-list@python.org> |
| In reply to | #5888 |
On Fri, May 20, 2011 at 5:07 PM, bvdp <bob@mellowood.ca> wrote: > You mention the tkinter group. Ummm, what group is that??? http://tkinter.unpythonic.net/wiki/TkinterDiscuss
[toc] | [prev] | [next] | [standalone]
| From | bvdp <bob@mellowood.ca> |
|---|---|
| Date | 2011-05-20 16:34 -0700 |
| Message-ID | <d85d06d3-09aa-4508-8924-83e4b2b85d13@18g2000prd.googlegroups.com> |
| In reply to | #5889 |
On May 20, 4:29 pm, Ian Kelly <ian.g.ke...@gmail.com> wrote: > On Fri, May 20, 2011 at 5:07 PM, bvdp <b...@mellowood.ca> 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,
[toc] | [prev] | [next] | [standalone]
| From | rantingrick <rantingrick@gmail.com> |
|---|---|
| Date | 2011-05-20 16:37 -0700 |
| Message-ID | <136b3435-a6bd-45fa-9c8c-5602ea23c861@s2g2000yql.googlegroups.com> |
| In reply to | #5888 |
On May 20, 6:07 pm, bvdp <b...@mellowood.ca> 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.
[toc] | [prev] | [next] | [standalone]
| From | bvdp <bob@mellowood.ca> |
|---|---|
| Date | 2011-05-21 17:07 -0700 |
| Message-ID | <ea980875-ac49-4563-a7c8-5b4683341bda@k27g2000pri.googlegroups.com> |
| In reply to | #5891 |
On May 20, 4:37 pm, rantingrick <rantingr...@gmail.com> wrote: > Thats sounds to me a lot like hammering square pegs though round > holes... Perhaps you should explain first in "plain english" what Ahh, but what fun would the Internet, Usenet and programming be without round holes and square pegs. I thought my English was pretty good. > problem your application is intended to solve, then how it is expected I'm trying very much to focus on the problem I'm having with a particular bit of python code. I'm not trying to have the community solve my coding problems. > 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. You want me to attach several hundred/thousand lines of source code to demonstrate that a particular bit of python has changed behavior between versions?
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2011-05-21 10:18 +0200 |
| Message-ID | <ir7shb$dd8$1@solani.org> |
| In reply to | #5867 |
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.
[toc] | [prev] | [next] | [standalone]
| From | bvdp <bob@mellowood.ca> |
|---|---|
| Date | 2011-05-21 17:03 -0700 |
| Message-ID | <fe3b6da7-4e9a-4226-bc6e-a271714c2df8@e17g2000prj.googlegroups.com> |
| In reply to | #5905 |
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.
[toc] | [prev] | [next] | [standalone]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2011-05-21 20:33 -0400 |
| Message-ID | <mailman.1891.1306024415.9059.python-list@python.org> |
| In reply to | #5941 |
On 5/21/2011 8:03 PM, bvdp wrote: > Yes, I can confirm that both the lambda and setting the class to: > > class selectFav(object): One of the purposes and advantages of Python 3 is having only one class system. Best to always use new-style classes in Python 2.2+ unless you understand and need old-style classes (and need should be never for most people). -- Terry Jan Reedy.
[toc] | [prev] | [next] | [standalone]
| From | bvdp <bob@mellowood.ca> |
|---|---|
| Date | 2011-05-21 19:20 -0700 |
| Message-ID | <42561028-39ce-4543-8e3c-b021e3a2b067@34g2000pru.googlegroups.com> |
| In reply to | #5944 |
> One of the purposes and advantages of Python 3 is having only one class > system. Best to always use new-style classes in Python 2.2+ unless you > understand and need old-style classes (and need should be never for most > people). > Thanks for this. I'll keep it in mind! One thing I really don't understand ... is there a difference between the old/new forms: class foo: class foo(): In cases where I've played with them, they _appear_ to work the same? Also, where does one find the magic that says that for a tkinter class you should use: class foo(object): Not really sure where "object" comes from. Thanks and best,
[toc] | [prev] | [next] | [standalone]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2011-05-22 17:17 -0400 |
| Message-ID | <mailman.1930.1306099067.9059.python-list@python.org> |
| In reply to | #5948 |
On 5/21/2011 10:20 PM, bvdp wrote: > >> One of the purposes and advantages of Python 3 is having only one class >> system. Best to always use new-style classes in Python 2.2+ unless you >> understand and need old-style classes (and need should be never for most >> people). >> > > Thanks for this. I'll keep it in mind! > > One thing I really don't understand ... is there a difference between > the old/new forms: > > class foo: > class foo(): > > In cases where I've played with them, they _appear_ to work the same? I believe they are. Same is true in 3.x except that the result in a new-style class. > Also, where does one find the magic that says that for a tkinter class > you should use: > > class foo(object): Perhaps nowhere. It may have been an unintended side-effect of the change in callable check, or intentional but not documented. > Not really sure where "object" comes from. It is the base class of all (new-style) classes. >>> object() <object object at 0x00EB6668> -- Terry Jan Reedy
[toc] | [prev] | [next] | [standalone]
| From | rantingrick <rantingrick@gmail.com> |
|---|---|
| Date | 2011-05-22 07:03 -0700 |
| Message-ID | <5a309bd1-71e1-4c78-a304-24552b1c5da5@m40g2000vbt.googlegroups.com> |
| In reply to | #5941 |
On May 21, 7:03 pm, bvdp <b...@mellowood.ca> wrote:
> 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.
Ok NOW we are getting somewhere! It is amazing how helpful people can
be when you explain your problem in "plain English". What you are
describing here is a dialog (be it modal or not). However your earlier
description of...
"""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. """
... was about as effective as the "orb of confusion" on Patrick...
*drool*
> 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.
Yes you ABSOLUTELY SHOULD encapsulate the dialog code in a class! THEN
create an instance of the class inside a "easy to call" function.
class MyDialog(blah):
blah,blah,blah
def show_dialog(*args):
d = MyDialog(*args)
return d.result
result = show_dialog()
...and they all lived happily ever after ;-)
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2011-05-23 00:25 +1000 |
| Message-ID | <mailman.1915.1306074309.9059.python-list@python.org> |
| In reply to | #5975 |
On Mon, May 23, 2011 at 12:03 AM, rantingrick <rantingrick@gmail.com> wrote: > ... was about as effective as the "orb of confusion" on Patrick... > *drool* > That sounds like a Dungeons and Dragons artifact item... invoking the orb of confusion is a standard action that does not provoke an Attack of Opportunity. > class MyDialog(blah): > blah,blah,blah > > def show_dialog(*args): > d = MyDialog(*args) > return d.result > > result = show_dialog() I don't really see why it shouldn't be valid to use the class itself in this way. Once the constructor returns, the object IS the return value. But then, my opinion may not be valid. I've done weird things in C++ where, for instance, the invocation of a modeless dialog is: new FoobarDialog(params); And somewhere it has an event (eg when the window is destroyed) that executes: delete this; I'm a little mad and generally silly, so my opinion doesn't matter (matter matter matter matter). But it did work, and the code was nice and clean! Chris Angelico
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web