开发者

Ruby + Tk command binding - scope issue?

开发者 https://www.devze.com 2022-12-11 11:12 出处:网络
So I have this app require \'tk\' class Foo def my_fancy_function puts \"hello, world!\" end def initialize

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 #<TkBut开发者_StackOverflow社区ton:..."

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?


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消