Ruby + Tk command binding - scope issue?

我怕爱的太早我们不能终老 提交于 2019-12-01 06:09:40

问题


So I have this app

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

But if I press the button, I get "NameError: undefined local variable or method `my_fancy_function' for #<TkButton:..."

I'm pretty sure I'm missing something trivial related to scope... how do I bind that command to the button correctly?

Edit: Okay, if I change my my_fancy_button block to parameters, i.e.

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

Then it works. But why?


回答1:


If you put a

p self

into the do ... end block of your code, then you'll probably find out that the current scope is different than your Foo object.




回答2:


Usually, passing blocks to Tk constructors is unnecessary. The resulting scope is confusing, so I think it should be discouraged.

Examples of same which contain only literal values are inflexible, and teach a bad habit.

Here, a minimal change to your program makes it work, while maintaining readability:

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

It works for me using Ruby 2.2.5 (with Tk 8.5.12) on Windows 7.



来源:https://stackoverflow.com/questions/1723101/ruby-tk-command-binding-scope-issue

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!