From: Shea Martin <
[email protected]>
Subject: tk app, reading output from command and put it in a text widget
Date: Thu, 6 Oct 2005 05:31:49 +0900
Message-ID: said:
I have a button which launches and externcal command. I want to capture
the output of that command and append it to my text area. Can I do this
with events?
Hmmm...
Maybe, TkTextIO class (a Tk sample included in Ruby-1.8.3) is useful.
For example,
-----------------------------------------------------------------------
require 'tk'
require 'open3'
# use TkTextIO class which is one of the sample scripts on Ruby source archive.
tk_sample_dir = '/usr/local/src/ruby-1.8.3/ext/tk/sample'
require File.join(tk_sample_dir, 'tktextio.rb')
f = TkFrame.new.pack
tio = TkTextIO.new(f, :show=>
os){
yscrollbar(TkScrollbar.new(f).pack
side=>:right, :fill=>:y))
pack
side=>:left, :fill=>:both, :expand=>true)
}
org_stdout = $stdout
$stdout = tio
$stderr = tio
# execute an external command
# ( In this way, cannot determine the output order between stdout and stderr. )
def ex_cmd(cmd)
p_in, p_out, p_err = *Open3.popen3(cmd)
[
p_in,
Thread.new{ p_out.each{|line| print(line) } },
Thread.new{ p_err.each{|line| print(line) } }
]
end
f = TkFrame.new.pack
fill=>:x,
adx=>40)
cmd = '/bin/cat - nofile' # external command
TkButton.new(f, :text=>'exec external command'){|b|
command {
b.state
disabled) # disable the button while ex_cmd is running
Thread.new{ # create a thread to avoid hang-up of the eventloop
begin
p_in, out_th, err_th = ex_cmd(cmd)
p_in.print("foo foo foo\n")
p_in.print("bar bar bar\n")
p_in.print("baz baz baz\n")
p_in.print("hoge hoge hogw\n")
p_in.print("fuga fuga fuga\n")
p_in.close_write
out_th.join
err_th.join
ensure
b.state
normal) # enable the button
end
}
}
}.pack
side=>:left)
# TkTextIO is a subclass of TkText
TkButton.new(f, :text=>'print log to console',
:command=>proc{org_stdout.print(tio.value)}).pack
side=>:right)
Tk.mainloop