How to use Ruby / Tk to display a text message status box

how can we pop up a Tk window to display the temporary results of a
program?

If our program is running and displaying its intermediate calculations,
instead of showing the final result at the end, i hope to have a Tk
window just to show the semi-final results.

would there be a simple way, just using a text box or something?

right now i have:

require ‘tk’

root = TkRoot.new {title “Ex1”}
TkLabel.new(root) do
text “Hello, world!”
pack(“padx”=> 15, “pady” => 15, “side” => “left”)
end
Tk.mainloop

[and my program]

but the program won’t run until i close the Tk window generated.

SpringFlowers AutumnMoon wrote:

how can we pop up a Tk window to display the temporary results of a
program?

The normal way to do this is in a GUI program is to use Threads …

right now i have:

Tk.mainloop

[and my program]

but the program won’t run until i close the Tk window generated.

When you call “mainloop”, you’re telling Tk (and other GUIs, too) to
wait for the user to do something (eg click a button). This is sometimes
called an “event loop”. As the “loop” name suggests, the program stops
at this point and nothing further will be run until the GUI is ended.

To run other tasks (such as your calculation) concurrently with the
event loop, start those other tasks in a ruby Thread alongside the GUI
code. Then, if you want to display intermediate results from that task
in the GUI, pass messages between the task thread to the main GUI
thread. Again, there’s numerous different ways to do this.

I haven’t used Ruby Tk so I’m not sure if it’s an issue, but in many
other toolkits, the non-GUI threads may starved of execution time - ie
the GUI event loop hogs the scheduler. So if you are finding your
background task is not progressing, you may need to set up a timed event
in the Tk code that passes control among the Threads (eg calling
Thread.pass)

hth
alex

Alex F. wrote:

SpringFlowers AutumnMoon wrote:

how can we pop up a Tk window to display the temporary results of a
program?

When you call “mainloop”, you’re telling Tk (and other GUIs, too) to
wait for the user to do something (eg click a button). This is sometimes
called an “event loop”. As the “loop” name suggests, the program stops
at this point and nothing further will be run until the GUI is ended.

To run other tasks (such as your calculation) concurrently with the
event loop, start those other tasks in a ruby Thread alongside the GUI
code. Then, if you want to display intermediate results from that task
in the GUI, pass messages between the task thread to the main GUI
thread. Again, there’s numerous different ways to do this.

what about not calling the MainLoop but just keep on painting on the GUI
window? For example, like in Win 32, I had a program that just popped
out a window and then I just keep on using DrawText to paint the result.
The whole program doesn’t need to have any event driven handling. just
drawing text to a window.

On Sep 24, 2007, at 7:34 AM, SpringFlowers AutumnMoon wrote:

at this point and nothing further will be run until the GUI is ended.
the GUI
window? For example, like in Win 32, I had a program that just popped
out a window and then I just keep on using DrawText to paint the
result.
The whole program doesn’t need to have any event driven handling.
just
drawing text to a window.

Since you propose an alternative solution, why did you not try it out
for yourself, rather than just throwing the question out on the
mailing list? You would have had the answer much quicker hat way.
Ruby is a very easy language to experiment with. That is one of its
greatest strengths. You should take advantage of it – it is the best
way to learn.

If you had tried your idea, you would have found that it doesn’t
work. Unless Tk.mainloop is called, Tk will never paint any windows
on the screen. The advice you received from Alex F. was good
advice. If handling threads is too difficult for you at the current
stage of your Ruby development, I suggest you print intermediate
results to stdout.

Regards, Morton

Morton G. wrote:

Since you propose an alternative solution, why did you not try it out
for yourself, rather than just throwing the question out on the
mailing list? You would have had the answer much quicker hat way.
Ruby is a very easy language to experiment with. That is one of its
greatest strengths. You should take advantage of it – it is the best
way to learn.

because i have no clue how that can be done. all the examples in a book
i found and on the web all do the MainLoop.

that is in the realm of Ruby / Tk and maybe someone knows a couple of
lines that can do it, or some code segment on a page.

On Sep 24, 2007, at 2:53 PM, SpringFlowers AutumnMoon wrote:

book
i found and on the web all do the MainLoop.

For the very good reason that there is no other way to make Ruby/Tk
to display anything.

that is in the realm of Ruby / Tk and maybe someone knows a couple of
lines that can do it, or some code segment on a page.

I very much doubt it. I will be happy to be proven wrong.

Regards, Morton

I wish they help you :

http://httpd.chello.nl/k.vangelder/ruby/learntk/
http://phrogz.net/ProgrammingRuby/ext_tk.html

http://members.at.infoseek.co.jp/shiroikumo/ruby/rubytk/index-en.html

On Sep 23, 2:46 pm, SpringFlowers AutumnMoon
[email protected] wrote:

how can we pop up aTkwindow to display the temporary results of a
program?

If our program is running and displaying its intermediate calculations,
instead of showing the final result at the end, i hope to have aTk
window just to show the semi-final results.

someone in the Tcl/Tk newsgroup posted a program to do that.
i don’t know the exact Ruby / Tk equivalent right now, but here is the
code that will work in Perl:

use warnings;
use strict;
use Tk qw/tkinit DoOneEvent exit DONT_WAIT ALL_EVENTS/;
use POSIX qw(strftime);

my $mw = tkinit;

my $text=$mw->Text()->pack();

my $I;
my $J = 0;

while (1) {
$mw->DoOneEvent( DONT_WAIT | ALL_EVENTS );
if ( ++$I > 10000 ) { #slows things down use 1 for max speed

   $text->delete("1.0", 'end');
   $text->insert('end',"And this is GUI $J ");
   my $now_string = strftime "%a %b %e %H:%M:%S %Y", localtime;
   $text->insert('end',"\ntime is $now_string ");

    print "command line $J ";
    $I = 0;
    $J++;
}

}

SpringFlowers AutumnMoon wrote:

If our program is running and displaying its intermediate calculations,
instead of showing the final result at the end, i hope to have aTk
window just to show the semi-final results.

the following program can do what the Perl program can do.
right now i don’t know Tk enough to check when the GUI window is closed
by the user and therefore don’t do any text update.

require ‘tk’

tk = TkRoot.new
text = TkText.new(tk).pack()

i = 0
n = 10000

while i += 1
TclTkLib.do_one_event(TclTkLib::EventFlag::ALL |
TclTkLib::EventFlag::DONT_WAIT)
if i % n == 0
text.delete(‘1.0’, ‘end’)
text.insert(‘end’, “This is GUI %d \n” % (i / n))
text.insert(‘end’, “Time is %s” % Time.now.strftime("%Y-%m-%d
%I:%M:%S"))
printf "This is command line %d ", i / n
end
end

Hi,

From: SpringFlowers AutumnMoon [email protected]
Subject: Re: how to use Ruby / Tk to display a text message status box
Date: Wed, 26 Sep 2007 21:08:44 +0900
Message-ID: [email protected]

the following program can do what the Perl program can do.
right now i don’t know Tk enough to check when the GUI window is closed
by the user and therefore don’t do any text update.

How about the following?

require ‘tk’

evloop = Thread.new{Tk.mainloop}
text = TkText.new(Tk.root).pack

i = 0
n = 10000

Tk.root.protocol(:WM_DELETE_WINDOW){
if Tk.messageBox(:type=>‘okcancel’, :message=>’ Realy? ') == ‘ok’
printf “Bye …\n”
exit
else
#ignore
end
}

while (text.exist? rescue false)
if (i += 1) % n == 0
text.value = <<EOS
This is GUI #{(i / n)}
Time is #{Time.now.strftime(“%Y-%m-%d %I:%M:%S”)}
EOS
printf “This is command line #{i / n}\n”
end
end

On Sep 26, 2007, at 9:21 AM, Hidetoshi NAGAI wrote:

Tk.root.protocol(:WM_DELETE_WINDOW){
text.value = <<EOS
This is GUI #{(i / n)}
Time is #{Time.now.strftime("%Y-%m-%d %I:%M:%S")}
EOS
printf “This is command line #{i / n}\n”
end
end

I had a little trouble when I tried to run your code. I kept getting
a segment fault at the point the code called the exit method. Maybe
it’s because I’m still running Ruby 1.8.2 on Mac OS X, and it
wouldn’t happen I had a new version of Ruby. However, I did get it to
run by moving the exit call to come after the Tk.mainloop message and
adding a Tk.root.destroy message to block given to the protocol method.

require 'tk'

tk_event_thread = Thread.new do
Tk.mainloop
puts “Bye…”
exit
end

progress_msg = TkText.new(Tk.root).pack

Tk.root.protocol(:WM_DELETE_WINDOW) {
if Tk.messageBox(:type=>‘okcancel’, :message=>‘Really?’) == ‘ok’
Tk.root.destroy
end
}

i = 0
loop do
i += 1
progress_msg.value = <<TEXT
This is GUI output #{i}
Time is #{Time.now.strftime("%Y-%m-%d %I:%M:%S")}
TEXT
puts “This is command line output #{i}”
sleep(1)
end

But thanks very much for posting your code. I learned several
important new things about Ruby/Tk from it.

Regards, Morton

Hidetoshi NAGAI wrote:

How about the following?

require ‘tk’

evloop = Thread.new{Tk.mainloop}
text = TkText.new(Tk.root).pack

i = 0
n = 10000

Tk.root.protocol(:WM_DELETE_WINDOW){
if Tk.messageBox(:type=>‘okcancel’, :message=>’ Realy? ') == ‘ok’
printf “Bye …\n”
exit
else
#ignore
end
}

while (text.exist? rescue false)
if (i += 1) % n == 0
text.value = <<EOS
This is GUI #{(i / n)}
Time is #{Time.now.strftime("%Y-%m-%d %I:%M:%S")}
EOS
printf “This is command line #{i / n}\n”
end
end

That’s looking great. I don’t know why but the line

while (text.exist? rescue false)

is not getting through (the text.exist? won’t be true).

right now i tweak a little bit of it and just make it

while (1)

and still tweaking it.

Morton G. wrote:

On Sep 26, 2007, at 9:21 AM, Hidetoshi NAGAI wrote:

Tk.root.protocol(:WM_DELETE_WINDOW){
text.value = <<EOS
This is GUI #{(i / n)}
Time is #{Time.now.strftime("%Y-%m-%d %I:%M:%S")}
EOS
printf “This is command line #{i / n}\n”
end
end

This is one example with Tk.mainloop running as a thread, and a
reporting loop running as a thread. I can’t pass “i” into the
report_and_sleep as “i” points to a constant instance of Fixnum. Needed
to create a counter object so that a reference to the counter instance
is passed, and the thread and extract the value from it:

require ‘tk’

tk = TkRoot.new
text = TkText.new(tk, ‘width’=>80, “height” => 60).pack()

class Counter
attr_accessor :i
end

i = 0
n = 300000

counter = Counter.new()

Tk.root.protocol(:WM_DELETE_WINDOW){
if Tk.messageBox(:type=>‘okcancel’, :message=>'Really exit? ') == ‘ok’
printf “Bye …\n”
exit
else
# ignore
end
}

def report_and_sleep(text, counter)
c = 0
time_start = Time.now
while 1
c += 1
sleep 3
text.value = <<EOS
This is report #{c}

This is GUI
The counter is #{counter.i}
It is doing #{(counter.i / (Time.now - time_start)).to_i} iterations per
second
Time is #{Time.now.strftime("%Y-%m-%d %I:%M:%S")}
EOS
end
end

evloop = Thread.new{ Tk.mainloop }
ev_report = Thread.new(){ report_and_sleep(text, counter) }

while (1)

i += 1
counter.i = i
if i % n == 0
printf "This is command line #{i / n} "
end
end

Waleed H. wrote:

I wish they help you :

http://httpd.chello.nl/k.vangelder/ruby/learntk/
Ruby Tk
Learn How to Blog and Build Websites for Profit!
http://members.at.infoseek.co.jp/shiroikumo/ruby/rubytk/index-en.html

Ready to use examples:

Jurij Veresciaka wrote:

Waleed H. wrote:

I wish they help you :

http://httpd.chello.nl/k.vangelder/ruby/learntk/
Ruby Tk
Learn How to Blog and Build Websites for Profit!
http://members.at.infoseek.co.jp/shiroikumo/ruby/rubytk/index-en.html

Ready to use examples:

http://rubytk.jurijveresciaka.com

http://rubytk.readytouseexamples.com

Jurij Veresciaka wrote:

Jurij Veresciaka wrote:

Waleed H. wrote:

I wish they help you :

http://httpd.chello.nl/k.vangelder/ruby/learntk/
Ruby Tk
Learn How to Blog and Build Websites for Profit!
http://members.at.infoseek.co.jp/shiroikumo/ruby/rubytk/index-en.html

Ready to use examples:

http://rubytk.jurijveresciaka.com

http://rubytk.readytouseexamples.com

Now all examples are here: http://www.readytouseexamples.com

Here you can find examples for JRuby, RubyTk, RubyGtk, RMagick

If however, you don’t want a separate reporting thread, this is it:

require ‘tk’

tk = TkRoot.new
text = TkText.new(tk, ‘width’=>80, “height” => 60).pack()

#text = TkText.new(Tk.root).pack

i = 0
n = 100000

Tk.root.protocol(:WM_DELETE_WINDOW){
if Tk.messageBox(:type=>‘okcancel’, :message=>'Really exit? ') == ‘ok’
printf “Bye …\n”
exit
else
# ignore
end
}

evloop = Thread.new{ Tk.mainloop }
while (1)

i += 1
if i % n == 0
text.value = <<EOS
This is GUI #{(i / n)}
Time is #{Time.now.strftime("%Y-%m-%d %I:%M:%S")}
EOS

printf "This is command line #{i / n} "

end
end