1

これはtkに固有のものではなく、ruby DSLとinstance_evalに関するより一般的な問題ですが、ここに私の質問があります。tkにDSLを使用したい場合、特定のものを機能させる方法がわかりません。たとえば、ボタンを押してインスタンスメソッドを呼び出したい場合、Tk親クラス(つまりTk :: Button)で同じ名前のメソッドを呼び出そうとしていると見なされるため、これは機能しません。以下のコード:

require 'tk'
class MyApp
  def initialize
    @root = TkRoot.new
    TkFrame.new {|f|
      TkButton.new(f) {
        text "Press Me"
        command proc {do_something()}
        pack
      }
      pack
    }
  end
  def do_something
    puts "Hello!"
  end
  def run
    Tk.mainloop
  end
end

MyApp.new.run

DSLを使用せずに書き直せば、この問題を回避できますが、さまざまな理由からDSLを好みます。

class MyApp
  def initialize
    @root = TkRoot.new
    f = TkFrame.new
    TkButton.new(f, text: "Press Me", command: proc {do_something()}).pack
    f.pack
  end
  def do_something
    puts "Hello!"
  end
  def run
    Tk.mainloop
  end
end

MyApp.new.run

MyAppクラスのインスタンス変数についても同じことが言えます。これを回避する方法はありますか?

4

1 に答える 1

2

proc { do_something }おそらくTkButtonインスタンスのコンテキストで評価されています。それはおそらくあなたがブロックの中にいる間にあなたtextが呼ぶことができる方法です。commandpack

これは事実上、インスタンスselfではなくなったことを意味します。インスタンスMyAppに変更されました。TkButton

これを試して:

def initialize
  my_app = self  # self is the MyApp instance here
  @root = TkRoot.new
  TkFrame.new do |f|
    TkButton.new f do
      text "Press Me"
      command proc { my_app.do_something }
      pack
    end
    pack
  end
end

ブロックはクロージャであるため、my_appローカル変数はブロックで使用できます。

于 2012-04-16T23:44:07.783 に答える