I know this is not specific to tk, but rather a more general problem with ruby DSLs and instance_eval, but here is my question, if I want to use the DSL for tk, I can’t figure out how to make certain things work. For example, if I want to call a instance method by pressing a button, this will not work, because it thinks I am trying to call a method with the same name in the Tk parent class (i.e. Tk::Button) as in the below code:
require 'tk'
class MyApp
def initialize
@root = TkRoot.new
TkFrame.new {|f|
TkButton.new(f) {
text "Press Me"
command proc {do_something()}
pack
}
pack
}
end
def do_something
puts "Hello!"
end
def run
Tk.mainloop
end
end
MyApp.new.run
If I rewrite it not using the DSL, I can avoid this issue, but I prefer the DSL for various reasons:
class MyApp
def initialize
@root = TkRoot.new
f = TkFrame.new
TkButton.new(f, text: "Press Me", command: proc {do_something()}).pack
f.pack
end
def do_something
puts "Hello!"
end
def run
Tk.mainloop
end
end
MyApp.new.run
The same is true for instance variables of the MyApp class. Is there any way arround this?
proc { do_something }is probably being evaluated in the context of theTkButtoninstance. That’s probably how you can calltext,commandandpackwhile inside the block.This effectively means
selfis not theMyAppinstance anymore; it was changed to theTkButtoninstance.Try this:
Since blocks are closures, the
my_applocal variable will be available to the block.