Tk DSL失去对实例方法和变量的访问权限?

时间:2012-04-16 23:24:46

标签: ruby tk

我知道这不是特定于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类的实例变量也是如此。这有什么办法吗?

1 个答案:

答案 0 :(得分:2)

proc { do_something }可能正在TkButton实例的上下文中进行评估。这可能就是您在阻止内部时调用textcommandpack的方式。

这实际上意味着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局部变量将可用于块。