0

The following code creates 3 buttons and adds a handler to each one. The Quit button works, the Give Up button produces an error NameError unknown option settings_change and suggests that an object has been deleted. Same with the Next button. The code works ok when I put the event handlers outside the class.

It turns out that if a callback is created by first doing something like next_note_proc = proc {next_note}, then in the button creation do command next_note_proc. Why does this work??

Why do the callbacks work differently when inside or outside the class?

require 'tk'
require 'tkextlib/tile'

class App

  def next_note
    puts "Got next note"
  end

  def settings_change
    puts "Got settings change"
  end

  def quit
    puts "Got exit"
    exit(1)
  end

  def initialize
    $number_correct = TkVariable.new;
    $mode = TkVariable.new

    @root = TkRoot.new {title "Music Training"}
    @content = Tk::Tile::Frame.new(@root) {padding "0 0 0 0"}.grid( :sticky => 'nsew')

    @a = Tk::Tile::Button.new(@content) {text 'Next'; command {next_note}}.grid( :column => 1, :row => 1, :sticky => 'w')
    @b = Tk::Tile::Button.new(@content) {text 'Give up'; command {settings_change}}.grid( :column => 2, :row => 1, :sticky => 'w')
    @c = Tk::Tile::Button.new(@content) {text 'Quit'; command {quit}}.grid( :column => 2, :row => 2, :sticky => 'w')
    TkWinfo.children(@content).each {|w| TkGrid.configure w, :padx => 0, :pady => 0}

    @c.bind("1") {quit}
    @a.bind("1") {next_note}
    @b.bind("1") {settings_change}

    puts "Starting up"
  end

   def run
     Tk.mainloop
   end  

end

the_app = App.new
the_app.run
qpit3a
  • 3
  • 3

1 Answers1

0

Commands executed from buttons run in the global context, but settings_change, quit and next_note are in the context of the class. When you use the proc command it creates a new Proc object which calls the method, and which can be called from other contexts.

The reason the quit command seems to work is probably because there is another quit command at the global scope that is getting called -- it is almost certainly not calling the quit method of the App object. You can verify that by adding a print statement in the quit method.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685