Forum: Ruby Ruby/Tk refresh problem

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Diego V. (Guest)
on 2009-04-06 14:40
(Received via mailing list)
Hello,
I am using Ruby 1.8.7 with Tk. The code runs fine. However, a few
instructions that I set while the program is busy (basically before
starting heavy computation it sets a TkLabel to display "Busy"... and
once it's done it sets it back to "") do not seem to have much of an
effect.

My fear is that it might be a problem like refreshing, whereby Tk
doesn't receive the instruction until it's too late. Is there a way to
flush all the instructions to Tk and let it do its magic before
continuing running my code?

Thanks.

Diego
Hidetoshi NAGAI (Guest)
on 2009-04-07 01:52
(Received via mailing list)
From: Diego V. <removed_email_address@domain.invalid>
Subject: Ruby/Tk refresh problem
Date: Mon, 6 Apr 2009 19:39:15 +0900
Message-ID:
<removed_email_address@domain.invalid>
> I am using Ruby 1.8.7 with Tk. The code runs fine. However, a few
> instructions that I set while the program is busy (basically before
> starting heavy computation it sets a TkLabel to display "Busy"... and
> once it's done it sets it back to "") do not seem to have much of an
> effect.

Maybe, you call the heavy computation *IN* a callback.
If so, that is a very bad way on event-driven programing.

The heavy part blocks the eventloop.
And then, the GUI cannot receive any events.
That is, the GUI seems to freeze.

A callback procedure should return as soon as possible.
One of the simple way to do that is to make a thread executing the
heavy computation.
Of course, you never join the thread in a callback.
Instead of joining, you should generate an event (TkVariable#wait may
be useful) to tell the finishing of the thread.

For example, the following is a bad sample.
------------------------------------------------------------------
require 'tk'
l = TkLabel.new(:text=>'MESSAGE').pack
TkTimer.new(500, -1,
            proc{l.foreground 'black'},
            proc{l.foreground 'red'}).start
TkButton.new(:text=>'start heavy work',
             :command=>proc{10.times{|n| sleep 1; p n}}).pack
Tk.mainloop
------------------------------------------------------------------
When clicking the button, this GUI seems to freeze.

Please compare with the following.
------------------------------------------------------------------
require 'tk'
l = TkLabel.new(:text=>'MESSAGE').pack
TkTimer.new(500, -1,
            proc{l.foreground 'black'},
            proc{l.foreground 'red'}).start
TkButton.new(:text=>'start heavy work',
             :command=>proc{Thread.new{10.times{|n| sleep 1; p
n}}}).pack
Tk.mainloop
------------------------------------------------------------------

The following is another sample.
------------------------------------------------------------------
require 'tk'
l = TkLabel.new(:text=>'MESSAGE').pack
TkTimer.new(500, -1,
            proc{l.foreground 'black'},
            proc{l.foreground 'red'}).start
b = TkButton.new(:text=>'start heavy work',
             :command=>proc{
                   b.state :disable
                   Thread.new{
                     10.times{|n| sleep 1; p n}
                     b.state :normal
                   }
                 }).pack
Tk.mainloop
Antonio G. (Guest)
on 2009-04-07 01:53
Have you tried "Tk.update" call ?

Antonio


Diego V. wrote:
> Hello,
> I am using Ruby 1.8.7 with Tk. The code runs fine. However, a few
> instructions that I set while the program is busy (basically before
> starting heavy computation it sets a TkLabel to display "Busy"... and
> once it's done it sets it back to "") do not seem to have much of an
> effect.
>
> My fear is that it might be a problem like refreshing, whereby Tk
> doesn't receive the instruction until it's too late. Is there a way to
> flush all the instructions to Tk and let it do its magic before
> continuing running my code?
>
> Thanks.
>
> Diego
This topic is locked and can not be replied to.