Привязка команды Ruby + 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 = 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' для #‹TkButton:..."

Я почти уверен, что упускаю что-то тривиальное, связанное с областью действия... как мне правильно связать эту команду с кнопкой?

Редактировать: Хорошо, если я изменю свой блок my_fancy_button на параметры, т.е.

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

Тогда это работает. Но почему?


person KTamas    schedule 12.11.2009    source источник


Ответы (2)


Если вы положите

p self

в блок do ... end вашего кода, то вы, вероятно, обнаружите, что текущая область видимости отличается от вашего объекта Foo.

person KARASZI István    schedule 21.01.2010

Обычно передача блоков конструкторам 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

У меня работает с Ruby 2.2.5 (с Tk 8.5.12) в Windows 7.

person MarkDBlackwell    schedule 23.04.2019
comment
См. также этот чрезвычайно ценный ответ, в котором объясняется область действия блока. - person MarkDBlackwell; 23.04.2019