Call method from a TK object

A

amnesiacx

Please can someone tell my why the code that follows works when the
"tick" and "zero" methods are nested inside "gui" , but when I move
the "tick" and "zero" methods out of gui - into a top level class
methods, the calls to tick from within the $stop object gets a "local
method not found" error? (You need TK libs to run)

# This script generates a counter with start and stop buttons.

class StopWatch

@@seconds=0
@@hundredths=0
@@stopped=TRUE
$heading = "Ticker"

#------------------------------------------------------------------------------
public

def initialize(head)
$heading = head
gui $heading
root = Tk.root
root.bind "Control-c", proc{root.destroy}
root.bind "Control-q", proc{root.destroy}
Tk.root.focus
Tk.mainloop
end

#------------------------------------------------------------------------------
private

def gui(head)

require "tk"

$title = TkLabel.new {
text head
relief 'raised'
width 20
font 'courier'
pack('side'=>'top', 'fill'=>'both')
}

$label = TkLabel.new {
text '0.00'
relief 'raised'
width 10
font 'verdana'
pack('side'=>'bottom', 'fill'=>'both')
}

$start = TkButton.new {
text 'Start'
command proc {
$stop.text "Stop"
if @@stopped
@@stopped = FALSE
tick
end
}

pack('side'=>'left','fill'=>'both','expand'=>'yes')
}

$stop = TkButton.new {
text 'Stop'
command proc{
text "Zero"
if @@stopped then
zero
text 'Stop'
end
@@stopped = TRUE
}

pack('side'=>'right','fill'=>'both','expand'=>'yes')
}

# the following two methods do not work when NOT nested inside
the gui method as they are now
# starts the timer
def tick
if @@stopped then return end
Tk.after 50, proc{tick}
@@hundredths+=5
if @@hundredths >= 100
@@hundredths=0
@@seconds+=1
end
$label.text format("%d.%02d", @@seconds,
@@hundredths)
end

# resets timer to zero
def zero
@@seconds=0
@@hundredths=0
$label.text format("%d.%02d", @@seconds,
@@hundredths)
end

end

end

#------------------------------------------------------------------------------
# run app
StopWatch.new("BIT Ruby Stop Watch!")
 
T

ts

a> $start = TkButton.new {

TkButton::new use #instance_eval, this mean that in the the block self is
$start

a> text 'Start'
a> command proc {
a> $stop.text "Stop"
a> if @@stopped
a> @@stopped = FALSE
a> tick

ruby try to call self.tick i.e. TkButton#tick and not StopWatch#tick, this
is why it give an error

a> $stop = TkButton.new {
a> text 'Stop'
a> command proc{
a> text "Zero"
a> if @@stopped then
a> zero

same here, it try to call TkButton#zero and not StopWatch#zero

a> text 'Stop'
a> end
a> @@stopped = TRUE
a> }



Guy Decoux
 
A

amnesiacx

a> $start = TkButton.new {

TkButton::new use #instance_eval, this mean that in the the block self is
$start

a> text 'Start'
a> command proc {
a> $stop.text "Stop"
a> if @@stopped
a> @@stopped = FALSE
a> tick

ruby try to call self.tick i.e. TkButton#tick and not StopWatch#tick, this
is why it give an error

a> $stop = TkButton.new {
a> text 'Stop'
a> command proc{
a> text "Zero"
a> if @@stopped then
a> zero

same here, it try to call TkButton#zero and not StopWatch#zero

a> text 'Stop'
a> end
a> @@stopped = TRUE
a> }



Guy Decoux

Nope, calling StopWatch.tick or StopWatch.zero doesnt work, "no such
method" (sic) error
 
T

ts

a> Nope, calling StopWatch.tick or StopWatch.zero doesnt work, "no such
a> method" (sic) error

You make the confusion between StopWatch::tich (class method) and
StopWatch#tick (instance method). Try this (see 'self_orig = self')

svg% cat b.rb
#!/usr/bin/ruby
class StopWatch

@@seconds=0
@@hundredths=0
@@stopped=TRUE
$heading = "Ticker"

def initialize(head)
$heading = head
gui $heading
root = Tk.root
root.bind "Control-c", proc{root.destroy}
root.bind "Control-q", proc{root.destroy}
Tk.root.focus
Tk.mainloop
end

private
def gui(head)

require "tk"
self_orig = self

$title = TkLabel.new {
text head
relief 'raised'
width 20
font 'courier'
pack('side'=>'top', 'fill'=>'both')
}

$label = TkLabel.new {
text '0.00'
relief 'raised'
width 10
font 'verdana'
pack('side'=>'bottom', 'fill'=>'both')
}

$start = TkButton.new {
text 'Start'
command proc {
$stop.text "Stop"
if @@stopped
@@stopped = FALSE
self_orig.tick
end
}
pack('side'=>'left','fill'=>'both','expand'=>'yes')
}

$stop = TkButton.new {
text 'Stop'
command proc{
text "Zero"
if @@stopped then
self_orig.zero
text 'Stop'
end
@@stopped = TRUE
}

pack('side'=>'right','fill'=>'both','expand'=>'yes')
}
end

protected
def tick
if @@stopped then return end
Tk.after 50, proc{tick}
@@hundredths+=5
if @@hundredths >= 100
@@hundredths=0
@@seconds+=1
end
$label.text format("%d.%02d", @@seconds, @@hundredths)
end

def zero
@@seconds=0
@@hundredths=0
$label.text format("%d.%02d", @@seconds, @@hundredths)
end

end

StopWatch.new("BIT Ruby Stop Watch!")

svg%


p.s. : public is useless with initialize (initialize is always private)


Guy Decoux
 
A

amnesiacx

a> Nope, calling StopWatch.tick or StopWatch.zero doesnt work, "no such
a> method" (sic) error

You make the confusion between StopWatch::tich (class method) and
StopWatch#tick (instance method). Try this (see 'self_orig = self')

svg% cat b.rb
#!/usr/bin/ruby
class StopWatch

@@seconds=0
@@hundredths=0
@@stopped=TRUE
$heading = "Ticker"

def initialize(head)
$heading = head
gui $heading
root = Tk.root
root.bind "Control-c", proc{root.destroy}
root.bind "Control-q", proc{root.destroy}
Tk.root.focus
Tk.mainloop
end

private
def gui(head)

require "tk"
self_orig = self

$title = TkLabel.new {
text head
relief 'raised'
width 20
font 'courier'
pack('side'=>'top', 'fill'=>'both')
}

$label = TkLabel.new {
text '0.00'
relief 'raised'
width 10
font 'verdana'
pack('side'=>'bottom', 'fill'=>'both')
}

$start = TkButton.new {
text 'Start'
command proc {
$stop.text "Stop"
if @@stopped
@@stopped = FALSE
self_orig.tick
end
}
pack('side'=>'left','fill'=>'both','expand'=>'yes')
}

$stop = TkButton.new {
text 'Stop'
command proc{
text "Zero"
if @@stopped then
self_orig.zero
text 'Stop'
end
@@stopped = TRUE
}

pack('side'=>'right','fill'=>'both','expand'=>'yes')
}
end

protected
def tick
if @@stopped then return end
Tk.after 50, proc{tick}
@@hundredths+=5
if @@hundredths >= 100
@@hundredths=0
@@seconds+=1
end
$label.text format("%d.%02d", @@seconds, @@hundredths)
end

def zero
@@seconds=0
@@hundredths=0
$label.text format("%d.%02d", @@seconds, @@hundredths)
end

end

StopWatch.new("BIT Ruby Stop Watch!")

svg%


p.s. : public is useless with initialize (initialize is always private)


Guy Decoux

Thx for the help. Appreciated.
 

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

Similar Threads

Ruby/tk Help Please 19
Ruby TK 2
Ruby/Tk 10
Ruby/Tk 4
[ANN] multiple Tk interpreter support 0
ruby/tk : hide TkFrame 1
A Tk window 20
[RFC] framework of Ruby/Tk + VNC 9

Members online

Forum statistics

Threads
473,981
Messages
2,570,187
Members
46,730
Latest member
AudryNolan

Latest Threads

Top