1

我知道这不是 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 类的实例变量也是如此。有什么办法解决这个问题吗?

4

1 回答 1

2

proc { do_something }可能正在TkButton实例的上下文中进行评估。这可能就是你可以调用的方式textcommand并且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局部变量将可用于块。

于 2012-04-16T23:44:07.783 回答