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.

···

--
Posted via http://www.ruby-forum.com/.

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

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++;
    }
}

···

On Sep 23, 2:46 pm, SpringFlowers AutumnMoon <summercooln...@gmail.com> 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.

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

···

--
Posted via http://www.ruby-forum.com/\.

I wish they help you :

http://httpd.chello.nl/k.vangelder/ruby/learntk/

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

···

On 9/26/07, Summercool <Summercoolness@gmail.com> wrote:

On Sep 23, 2:46 pm, SpringFlowers AutumnMoon > <summercooln...@gmail.com> 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++;
    }
}

--

Yours,
Waleed Harbi
Nothing without reason everything for some thing.

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

···

--
Posted via http://www.ruby-forum.com/\.

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

···

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

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

Hi,

···

From: SpringFlowers AutumnMoon <summercoolness@gmail.com>
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: <2363af4d260f503c8c1666a3236b4ad4@ruby-forum.com>

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
----------------------------------------------------------------
--
Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)

Waleed Harbi 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

···

--
Posted via http://www.ruby-forum.com/\.

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

···

--
Posted via http://www.ruby-forum.com/\.

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.

···

--
Posted via http://www.ruby-forum.com/\.

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.

<code>
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
</code>

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

Regards, Morton

···

On Sep 26, 2007, at 9:21 AM, 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

Jurij Veresciaka wrote:

Waleed Harbi 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

···

--
Posted via http://www.ruby-forum.com/\.

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

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

···

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

Morton Goldberg 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

···

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

--
Posted via http://www.ruby-forum.com/\.

Jurij Veresciaka wrote:

Jurij Veresciaka wrote:

Waleed Harbi wrote:

I wish they help you :

http://httpd.chello.nl/k.vangelder/ruby/learntk/
http://phrogz.net/ProgrammingRuby/ext_tk.html
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

···

--
Posted via http://www.ruby-forum.com/\.

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

···

--
Posted via http://www.ruby-forum.com/.