Interactive ruby/tk app (was: ruby/tk internals)

Hello,

I am trying to achieve the same thing what is the default in tck/tk: I
start the application, and afterwards I can execute statements, changing
the user interface, creating new objects.

My first thought was the following:

···

evalFrame=TkFrame.new { pack }
evalBox=TkText.new(evalFrame) {
height 10
pack(‘fill’=>‘x’)
}
evalBtn=TkButton.new(evalFrame) {
text "Execute"
command proc {evalText(evalBox.value)}
pack()
}

def evalText(text)
puts eval text
end

The problem is, if I create a new Tk object runtime (a TkButton, for
example), I cannot store it into a local variable, as I will not be able
to reference that (was-local) variable.

While I was writing this mail, it came to my mind that I can pass a
Binding object to eval(). So, the solution is:


$topContext=binding()

def evalText(text)
puts eval text, $topContext
end

It looks better. Are there other (more pretty :slight_smile: solutions?

Bye:
Circum

Ferenc Engard wrote:


$topContext=binding()

def evalText(text)
puts eval text, $topContext
end

It looks better. Are there other (more pretty :slight_smile: solutions?

You appear to be learning by reading the docs for each part, then seeing
how to put them together one by one.

Learn by downloading the ruby tk examples; e-search for
"ruby-tk81-demos-english", then take one of the (overgrown) examples and
(painstakingly) remove each bit you don’t need. A vaguely OO model will pop
out.

Then find alternative examples and read them.

···


Phlip
http://www.greencheese.org/PhilosophyBrethrenThree
– Please state the nature of the programming emergency –

You appear to be learning by reading the docs for each part, then seeing
how to put them together one by one.

Learn by downloading the ruby tk examples; e-search for
"ruby-tk81-demos-english", then take one of the (overgrown) examples and
(painstakingly) remove each bit you don’t need. A vaguely OO model will pop
out.

I have looked for ruby-tk81-demos-english (and other) examples, but
didn’t find what I am looking for. I am trying to learn from the source,
but there are things what I cannot figure out.

For example, the following example:

#!/usr/bin/ruby
require "tk"
ctx=binding()
Tk::INTERP._eval(“set a blahblah”)
eval ‘Tk::INTERP._eval(“puts $a”)’,ctx

Returns “blahblah”, so it works as I expect.

With the following, I have problems:

···

#!/usr/bin/ruby
require “tk”
$topContext=binding()
evalFrame=TkFrame.new { pack }
evalBox=TkText.new(evalFrame) {
height 10
pack(‘fill’=>‘x’)
}
evalBtn=TkButton.new(evalFrame) {
text "Execute"
command proc {evalText(evalBox.value)}
pack()
}
c=TkCanvas.new {
background "white"
pack(“fill”=>“both”)
}

def evalText(text)
begin
puts eval text,$topContext
rescue Exception => e
puts "Error running script: #{e}"
end
end

Tk.mainloop

This is a test script, for executing ruby code runtime in the top
context, as I have mentioned in my previous post. Try it out, if it is
not clear!

If I evaluate the following text with it:

Tk::INTERP._eval(“set a blahblah”)
Tk::INTERP._eval(“puts $a”)

It returns “blahblah” -> Ok.

BUT! If I evaluate the two lines step by step (i.e. with two
button-clicks), then I receive this:

blahblah <-- after 1st click, the value of first eval()

Error running script: c:/ruby/lib/ruby/1.6/tk.rb:971:in `_eval’: can’t
read “a”: no such variable <-- after 2nd click, a is not defined! :open_mouth:

Also, if I execute the string

Tk::INTERP._eval(“puts [info vars]”)

It results only one variable, “args”, with the value “c0000”.

I know the solution is somewhere with the tk package’s callback
mechanism, but I cannot figure it out. Could somebody describe it,
please?

Thanks:
Circum

“Ferenc Engard” wrote:

#!/usr/bin/ruby
require "tk"
ctx=binding()
Tk::INTERP._eval(“set a blahblah”)
eval ‘Tk::INTERP._eval(“puts $a”)’,ctx

Why are you rooting around under the hood? If you want Tcl you know where to
get it.

Answering why you think you need to mess with systems private to RubyTk will
help us answer the questions.

···


Phlip

Phlip wrote:

“Ferenc Engard” wrote:

#!/usr/bin/ruby
require "tk"
ctx=binding()
Tk::INTERP._eval(“set a blahblah”)
eval ‘Tk::INTERP._eval(“puts $a”)’,ctx

Why are you rooting around under the hood? If you want Tcl you know where to
get it.

Believe or not, I love ruby. :-p I have always loved scripting
languages, and used tcl many times. (Unfortunately, I didn’t code
anything complicated in Tk). Now I have found ruby, trying to code
programs with GUI, and the obvious GUI choce is Tk for me.

I am actually writing a network traffic meter, and if I write it only
with ruby/tk objects, it is painfully slow. Yes, I could write it in
tcl, but I want it to write in ruby, only (?) the canvas’ object
handling needs some performance tuning, which I can easily code in tcl.

Anyway, the question above interests me irrespectively of my actual
problem.

Answering why you think you need to mess with systems private to RubyTk will
help us answer the questions.

Another task which needed to access tcl directly was require()ing tcl/tk
libraries. I am happy with using two (great) languages to help each
other; ruby is great in its well-designed OO support, tcl is
better/faster for me manipulating tk widgets.

Circum