TkTimer and calling own methods from handler

Hi!
I'm experimenting with Ruby Tcl/Tk and I've got stuck with timers. I
reduced my problem to following example:

#!/usr/bin/env ruby
require "tk"

def advance
  button.text = global_var.to_s
  global_var += 1
end

global_var = 0

root = TkRoot.new(:title=>'Example')
button = TkButton.new(root) {
  text "button"
}
button.pack("side"=>"right", "fill"=>"y")
tick = proc{|aobj|
  advance
}
timer = TkTimer.new(250, -1,tick )
timer.start(0)

Tk.mainloop()

I want this code to increase number displayed on button, but does not
work. When I change timer definition to:

tick = proc{|aobj|
   button.text = global_var.to_s
  global_var += 1
}

It does work, so it looks like I need to call my own method some
special way? I have examined examples in Ruby source code, but all of
them operates without wrapping code in own methods (I suppose to make
it easier to understand).

So how I should call own methods?

···

--
Witold Rugowski
http://nhw.pl/wp/ (EN blog)
http://FriendsFeedMe.com

I'm experimenting with Ruby Tcl/Tk and I've got stuck with timers. I
reduced my problem to following example:

#!/usr/bin/env ruby
require "tk"

def advance
  button.text = global_var.to_s
  global_var += 1
end

Both variables (button and global_variable) are local to the advance method and are not the same as the local variables button and global_variable defined below. This is the source of your problem.

global_var = 0

root = TkRoot.new(:title=>'Example')
button = TkButton.new(root) {
  text "button"
}
button.pack("side"=>"right", "fill"=>"y")
tick = proc{|aobj|
  advance
}
timer = TkTimer.new(250, -1,tick )
timer.start(0)

Tk.mainloop()

<snip>

So how I should call own methods?

One solution is to use real global variables.

<code>
#!/usr/bin/env ruby
require "tk"

def advance
   $button.text = $global_var.to_s
   $global_var += 1
end

$global_var = 0

root = Tk.root
root.title('Example')
win_w, win_h, win_y = 150, 50, 50
win_x = (root.winfo_screenwidth - win_w) / 2
root.geometry("#{win_w}x#{win_h}+#{win_x}+#{win_y}")
root.resizable(false, false)

$button = TkButton.new(root, :text => "button")
$button.pack(:fill => :both, :expand => true)
TkTimer.new(250, -1) { advance }.start

Tk.mainloop
</code>

Another, and IMO better, solution is take advantage of Ruby being object-oriented.

<code>
#!/usr/bin/env ruby
require "tk"

class MyButton
    def initialize(parent)
       @count = 0
       @me = TkButton.new(parent).pack(:fill => :both, :expand => true)
       TkTimer.new(250, -1) { advance }.start
    end
    def advance
       @count += 1
       @me.text(@count.to_s)
    end
end

root = Tk.root
root.title('Example')
win_w, win_h, win_y = 150, 50, 50
win_x = (root.winfo_screenwidth - win_w) / 2
root.geometry("#{win_w}x#{win_h}+#{win_x}+#{win_y}")
root.resizable(false, false)

MyButton.new(root)

Tk.mainloop
</code>

Regards, Morton

···

On Aug 21, 2007, at 8:15 AM, NetManiac wrote: