Привязка команды Ruby + Tk - проблема с областью действия? - PullRequest
4 голосов
/ 12 ноября 2009

Так что у меня есть это приложение

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» для #

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

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

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

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

Ответы [ 2 ]

5 голосов
/ 22 января 2010

Если поставить

p self

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

0 голосов
/ 23 апреля 2019

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

...