我知道这不是特定于tk,而是ruby DSL和instance_eval的更普遍的问题,但是这是我的问题,如果我想将DSL用于tk,我无法弄清楚如何确定事情有效。例如,如果我想通过按下按钮调用实例方法,这将无法工作,因为它认为我试图在Tk父类(即Tk :: Button)中调用一个具有相同名称的方法,如同下面的代码:
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
如果我不使用DSL重写它,我可以避免这个问题,但出于各种原因我更喜欢DSL:
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
对于MyApp类的实例变量也是如此。这有什么办法吗?
答案 0 :(得分:2)
proc { do_something }
可能正在TkButton
实例的上下文中进行评估。这可能就是您在阻止内部时调用text
,command
和pack
的方式。
这实际上意味着self
不再是MyApp
个实例;它已更改为TkButton
实例。
试试这个:
def initialize
my_app = self # self is the MyApp instance here
@root = TkRoot.new
TkFrame.new do |f|
TkButton.new f do
text "Press Me"
command proc { my_app.do_something }
pack
end
pack
end
end
由于块是闭包,my_app
局部变量将可用于块。