4

所以我有这个应用程序

require 'tk'
class Foo
  def my_fancy_function
    puts "hello, world!"
  end

  def initialize
    @root = TkRoot.new{title "Hello, world!"}
    frame = TkFrame.new
    my_fancy_button = TkButton.new(frame) do
      text "Press meee"
      command {my_fancy_function}
      pack
    end
    frame.pack
    Tk.mainloop
  end
end

bar = Foo.new

但是如果我按下按钮,我会得到“NameError:未定义的局部变量或方法 `my_fancy_function' for #<TkButton:...”

我很确定我错过了与范围相关的一些琐碎内容......如何正确将该命令绑定到按钮?

编辑:好的,如果我将my_fancy_button块更改为参数,即

my_fancy_button = TkButton.new(frame, :text => "Press meee", :command => proc{my_fancy_function}).pack

然后它工作。但为什么?

4

2 回答 2

5

如果你放一个

p self

进入do ... end代码块,那么您可能会发现当前范围与您的Foo对象不同。

于 2010-01-21T21:36:04.790 回答
0

通常,将块传递给Tk构造函数是不必要的。由此产生的范围令人困惑,所以我认为应该不鼓励这样做。

仅包含文字值的相同示例是不灵活的,并且会养成坏习惯。

在这里,对您的程序进行最小的更改即可使其工作,同时保持可读性:

require 'tk'
class Foo
  def my_fancy_function
    puts "hello, world!"
  end

  def initialize
    @root = TkRoot.new{title "Hello, world!"}
    frame = TkFrame.new
    my_fancy_button = begin
      b = TkButton.new frame
      b.text "Press meee"
      b.command {my_fancy_function}
      b.pack
    end
    frame.pack
    Tk.mainloop
  end
end

bar = Foo.new

它适用于我在 Windows 7 上使用 Ruby 2.2.5(带有 Tk 8.5.12)。

于 2019-04-23T20:02:13.853 回答