TkTimer and calling own methods from handler

N

NetManiac

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?
 
M

Morton Goldberg

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()

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,979
Messages
2,570,185
Members
46,728
Latest member
FernMcmull

Latest Threads

Top