1# -*- coding: utf-8 -*- 2# 3# animated wave demo (called by 'widget') 4# 5# based on Tcl/Tk8.5a2 widget demos 6 7# destroy toplevel widget for this demo script 8if defined?($aniwave_demo) && $aniwave_demo 9 $aniwave_demo.destroy 10 $aniwave_demo = nil 11end 12 13# create toplevel widget 14$aniwave_demo = TkToplevel.new {|w| 15 title("Animated Wave Demonstration") 16 iconname("aniwave") 17 positionWindow(w) 18} 19 20base_frame = TkFrame.new($aniwave_demo).pack(:fill=>:both, :expand=>true) 21 22# create label 23msg = TkLabel.new(base_frame) { 24 font $font 25 wraplength '4i' 26 justify 'left' 27 text 'このデモでは、ラインアイテムが一つだけ描かれたキャンバスウィジェットが表示されています。アニメーション処理は、そのラインアイテムの座標値を変更することで実現しています。' 28} 29msg.pack('side'=>'top') 30 31# create frame 32TkFrame.new(base_frame) {|frame| 33 TkButton.new(frame) { 34 #text '了解' 35 text '閉じる' 36 command proc{ 37 tmppath = $aniwave_demo 38 $aniwave_demo = nil 39 tmppath.destroy 40 } 41 }.pack('side'=>'left', 'expand'=>'yes') 42 43 TkButton.new(frame) { 44 text 'コード参照' 45 command proc{showCode 'aniwave'} 46 }.pack('side'=>'left', 'expand'=>'yes') 47 48}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m') 49 50# animated wave 51class AnimatedWaveDemo 52 def initialize(frame, dir=:left) 53 @direction = dir 54 55 # create canvas widget 56 @c = TkCanvas.new(frame, :width=>300, :height=>200, 57 :background=>'black') 58 @c.pack(:padx=>10, :pady=>10, :expand=>true) 59 60 # Creates a coordinates list of a wave. 61 @waveCoords = [] 62 @backupCoords = [] 63 n = 0 64 (-10..300).step(5){|n| @waveCoords << [n, 100]; @backupCoords << [n, 100] } 65 n = 305 66 @waveCoords << [n, 0]; @backupCoords << [n, 0] 67 @waveCoords << [n+5, 200]; @backupCoords << [n+5, 200] 68 @coordsLen = @waveCoords.length 69 70 # Create a smoothed line and arrange for its coordinates to be the 71 # contents of the variable waveCoords. 72 @line = TkcLine.new(@c, @waveCoords, 73 :width=>1, :fill=>'green', :smooth=>true) 74 75 # Main animation "loop". 76 # Theoretically 100 frames-per-second (==10ms between frames) 77 @timer = TkTimer.new(10){ basicMotion; reverser } 78 79 # Arrange for the animation loop to stop when the canvas is deleted 80 @c.bindtags_unshift(TkBindTag.new('Destroy'){ @timer.stop }) 81 end 82 83 # Basic motion handler. Given what direction the wave is travelling 84 # in, it advances the y coordinates in the coordinate-list one step in 85 # that direction. 86 def basicMotion 87 @backupCoords, @waveCoords = @waveCoords, @backupCoords 88 (0...@coordsLen).each{|idx| 89 if @direction == :left 90 @waveCoords[idx][1] = @backupCoords[(idx+1 == @coordsLen)? 0: idx+1][1] 91 else 92 @waveCoords[idx][1] = @backupCoords[(idx == 0)? -1: idx-1][1] 93 end 94 } 95 @line.coords(@waveCoords) 96 end 97 98 # Oscillation handler. This detects whether to reverse the direction 99 # of the wave by checking to see if the peak of the wave has moved off 100 # the screen (whose size we know already.) 101 def reverser 102 if @waveCoords[0][1] < 10 103 @direction = :right 104 elsif @waveCoords[-1][1] < 10 105 @direction = :left 106 end 107 end 108 109 # animation control 110 def move 111 @timer.start 112 end 113 114 def stop 115 @timer.stop 116 end 117end 118 119# Start the animation processing 120AnimatedWaveDemo.new(base_frame, :left).move 121