问题
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