[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

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

SpringFlowers AutumnMoon

9/23/2007 9:47:00 PM

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

15 Answers

Alex Fenton

9/24/2007 9:38:00 AM

0

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

SpringFlowers AutumnMoon

9/24/2007 11:34:00 AM

0

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

Morton Goldberg

9/24/2007 6:18:00 PM

0

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.

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

SpringFlowers AutumnMoon

9/24/2007 6:53:00 PM

0

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

Morton Goldberg

9/24/2007 9:01:00 PM

0

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

> 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

SpringFlowers AutumnMoon

9/26/2007 4:07:00 AM

0


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




SpringFlowers AutumnMoon

9/26/2007 12:09:00 PM

0


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

Hidetoshi NAGAI

9/26/2007 1:21:00 PM

0

SpringFlowers AutumnMoon

9/30/2007 8:31:00 AM

0

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

Morton Goldberg

9/30/2007 2:55:00 PM

0

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

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