2012-04-16 72 views
1

我知道這不是特定於tk,而是ruby DSLs和instance_eval更常見的問題,但這裏是我的問題,如果我想使用DSL的tk,我無法弄清楚如何使某些東西工作。例如,如果我想通過按下一個按鈕來調用一個實例方法,這將不起作用,因爲它認爲我正試圖調用Tk父類(即Tk :: Button)中的同名方法下面的代碼:Tk DSL無法訪問實例方法和變量?

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類。這有什麼辦法嗎?

回答

2

proc { do_something }可能正在對TkButton實例的上下文中進行評估。這可能是你可以在塊內部調用textcommandpack

這實際上意味着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局部變量將提供給該塊。

+1

這樣做,謝謝。 – 2012-04-16 23:50:22