1#!/usr/bin/env ruby
2# This script is a re-implementation of tktimer.rb with TkTimer(TkAfter) class.
3
4require "tk"
5
6root = TkRoot.new(:title=>'realtime timer sample')
7
8f1 = TkFrame.new(:borderwidth=>2, :relief=>:ridge)
9f1.pack(:side=>:bottom, :fill=>:both)
10TkLabel.new(f1, :text=>'use TkTimer (TkAfter) class').pack(:anchor=>:center)
11label1 = TkLabel.new(:parent=>f1, :relief=>:raised,
12                     :width=>10).pack(:fill=>:both)
13
14f2 = TkFrame.new(:borderwidth=>2, :relief=>:ridge)
15f2.pack(:side=>:bottom, :fill=>:both)
16TkLabel.new(f2, :text=>'use TkRTTimer class').pack
17label2 = TkLabel.new(:parent=>f2, :relief=>:raised,
18                     :width=>10).pack(:fill=>:both)
19
20TkLabel.new(:padx=>10, :pady=>5, :justify=>'left', :text=><<EOT).pack
21Interval setting of each timer object is 10 ms.
22Each timer object counts up the value on each callback
23(the value is not the clock data).
24The count of the TkTimer object is delayed by execution
25time of callbacks and inaccuracy of interval.
26On the other hand, the count of the TkRTTimer object is
27not delayed. Its callback interval is not accurate too.
28But it can compute error correction about the time when
29a callback should start.
30EOT
31
32# define the procedure repeated by the TkTimer object
33tick = proc{|aobj| #<== TkTimer object
34  cnt = aobj.return_value + 1  # return_value keeps a result of the last proc
35  label = aobj.current_args[0]
36  label.text format("%d.%02d", *(cnt.divmod(100)))
37  cnt #==> return value is kept by TkTimer object
38      #    (so, can be send to the next repeat-proc)
39}
40
41timer1 = TkTimer.new(10, -1, [tick, label1])    # 10 ms interval
42timer2 = TkRTTimer.new(10, -1, [tick, label2])  # 10 ms interval
43
44timer1.start(0, proc{ label1.text('0.00'); 0 })
45timer2.start(0, proc{ label2.text('0.00'); 0 })
46
47b_start = TkButton.new(:text=>'Start', :state=>:disabled) {
48  pack(:side=>:left, :fill=>:both, :expand=>true)
49}
50
51b_stop  = TkButton.new(:text=>'Stop', :state=>:normal) {
52  pack('side'=>'left', 'fill'=>'both', 'expand'=>'yes')
53}
54
55b_start.command {
56  timer1.continue
57  timer2.continue
58  b_stop.state(:normal)
59  b_start.state(:disabled)
60}
61
62b_stop.command {
63  timer1.stop
64  timer2.stop
65  b_start.state(:normal)
66  b_stop.state(:disabled)
67}
68
69TkButton.new(:text=>'Reset', :state=>:normal) {
70  command { timer1.reset; timer2.reset }
71  pack(:side=>:right, :fill=>:both, :expand=>:yes)
72}
73
74ev_quit = TkVirtualEvent.new('Control-c', 'Control-q')
75Tk.root.bind(ev_quit, proc{Tk.exit}).focus
76
77Tk.mainloop
78