I've been having a play with Tkinter, and I've ported across
a program that I wrote while learning VB, but I've had one
problem. There's one step that has a chunk of processing
which takes a few seconds to complete. In the old program, I
changed the cursor to an hourglass at the start, and reset
when the program finished. Trying to do the same in the new
version doesn't seem to work:
self.btnIterate['state'] = DISABLED # after the call to
self.btnClear['state'] = DISABLED # update_idletasks,
# the buttons are
# disabled, but...
self.root['cursor'] = 'wait' # ...this doesn't happen.
self.root.update_idletasks()
# do some processing... (cursor is an arrow)
self.btnIterate['state'] = NORMAL
self.btnClear['state'] = NORMAL
self.root['cursor'] = 'arrow'
# after the callback processing is finished the cursor is
# still the arrow - if I comment this out, the cursor
# does change, but not until the callback processing
# finishes.
It looks like update_idletasks() doesn't do cursors - is this
correct? (I looked in all the answer-type places of which I
could think.)
Xtian
[snip]
No Tk expert, but as I recall, this is a general problem with Tk.
Even murkier: I think Tk schedules the cursor-change which
means, of course, that it doesn't happen until too late. (Java's
AWT had/has? the same problem but even worse - it would
get confused and leave the cursor in the wrong state).
The work-around that I saw wasn't, to my mind, worth the
effort, and I decided to be satisfied with the button remaining
depressed. But perhaps the eff-bot has a more elegant
solution.
- Gordon
Hmmm. I tried changing the call to update_idletasks() to update()
(having read eff-bot's warning not to use it in callback events for
fear of producing race conditions), and it works. Maybe it's only OK
because I've disabled the button which invokes the callback, so we
don't get any contention? (Ooh, it looks like I can double click the
button before it disables. Probably that could do something nasty in
a more interesting application.) So I guess it's not the best plan,
but it'll do for this one.
Anyway, thanks for the answer, even if it was a "Yup, that's a problem
alright".
(Actually, that's a relatively comforting response. I'd hate
to be caught asking a "Read the documentation, second page, third
sentence"-response-getting question. And there's gotta be a better
way to have been putting that. Darn.)
Have a day!
Xtian
"I'd rather be rich than stupid."
I managed to kludge my way around this problem using the
following technique:
root = Tkinter._default_root
x, y = root.winfo_pointerxy()
w = root.winfo_containing(x, y)
if w:
old_cursor = w['cursor']
w.configure(cursor = "watch")
w.update()
w.configure(cursor = old_cursor)
This finds the widget that the mouse pointer happens to be
over, changes its cursor, and forces this to become the
current cursor by doing an update. The change back again
doesn't take effect until the event loop is returned to
or another update occcurs.
(This works on Windows, and will probably work on the Mac
(if Tkinter works there at all). It almost certainly won't
work on unix under X, because X maintains the cursor
continuously.)
Greg