まつもと ゆきひろです

In message "[ruby-list:4272] [Q] tk ext..."
    on 97/09/11, Kikutani Makoto <kikutani / jdc.ericsson.se> writes:

|[1  <text/plain; iso-2022-jp (7bit)>]
|きくたにです。
|
|そろそろ、rubyで実用プログラムを書きたいので、添削をお願いしようと
|思います。

おおっ.

|1) 標準入力はいずれUnixソケットからの入力に置き換えますが、この調子で
|  膨大なデータを受けとっていって、TkのCanvasは問題ないですか?
|  (あとズーム機能など入れなくちゃだめだし)

こいつはTkの問題なので私は良くわからんです.どうなんでしょう? 
どなたかご存知ありません?

|2) WViewerクラス中で使っている、$v, $c, $scrは最初インスタンス変数にして
|  たのですが、大域変数にしないとだめでした。これはそういうものですか?

この場所ではselfがすりかわっていますので,インスタンス変数は
Frameのものになってしまいます.ここはイテレータブロックの中
で生成するのではなく,

  @frm = TkFrame.new {
    ...
  }

  @v = TkCanvas.new(@frm) {
    ..
  }

というスタイルをお勧めしたいです.
# やはりselfをすりかえるという発想に無理があったか.

|3) draw_scaleというメソッドでやっていることは、最初、
|  $v = TkCanvas.new(f){ ... } の直後でやってたのですが、表示が変でした。
|  これはなぜ?

こちらでは再現しなかったので,よくわかりません.

|4) その他直したほうがいい点

その方が良いかどうかはわからないのですが,ハッシュを使って初
期化する版を作ってみました.また,インスタンス変数を使うよう
にもしています.

#!/usr/bin/ruby
# test program for WaveViewer which can be called from Verilog PLI

require "tkclass"

# initial window size
$width = '500'
$height = '100'
$vwidth = 30
$pr_time_step = 100

class WViewer
  def initialize(signame)
    @high = $height.to_i * 0.2
    @low = $height.to_i * 0.7
    @pr_time = 0
    @last_x = 0
    @last_y = @low

    @frm = TkFrame.new

    TkLabel.new(@frm, 'text'=>signame).pack('side' =>'top')

    # canvas for vertical axis
    @v = TkCanvas.new(@frm,
		      'relief' => 'sunken',
		      'bg' => 'LightCyan1',
		      'height' => $height,
		      'width' =>  $vwidth.to_s).pack('side' =>'left', 'fill'=>'y')

    # canvas for plotting the points
    @c = TkCanvas.new(@frm,
		      'relief' => 'sunken',
		      'bg' => 'LightCyan1',
		      'height' => $height,
		      'width' =>  $width,
		      'closeenough' => '3').pack('side' =>'top', 'fill'=>'both', 'expand'=>'1')
    draw_scale
    @c.xscrollcommand proc{|idx|
      @scr.set *idx
    }
  
    @scr = TkScrollbar.new(@frm,
			   'orient' => 'horizontal'). pack('side'=>'bottom', 'fill'=>'x')
    @scr.command proc{|idx|
      @c.xview *idx
    }
    @frm.pack
  end

  def draw_scale
    # draw vertical scale
    TkcLine.new(@v, $vwidth/2+10, @low, $vwidth/2+10, @high, 'fill'=>'blue')
    TkcLine.new(@v, $vwidth/2, @low, $vwidth/2+10, @low, 'fill'=>'blue')
    TkcLine.new(@v, $vwidth/2, @high, $vwidth/2+10, @high, 'fill'=>'blue')
    TkcText.new(@v, 5, @high, 'text'=>'1', 'fill'=>'red')
    TkcText.new(@v, 5, @low, 'text'=>'0', 'fill'=>'red')
  end

  def plot_bit(dt, b)
    x = @last_x + dt
    if b == 1
      y = @high
    else
      y = @low
    end
    TkcLine.new(@c, @last_x, @last_y, x, @last_y)
    TkcLine.new(@c, x, @last_y, x, y)
    if x >= @pr_time
      TkcText.new(@c, x, @low+10, 'text'=>x, 'fill'=>'green')
      @pr_time += $pr_time_step
    end
    @last_x = x
    @last_y = y
  end

  def set_scrarea
    @c.configure('scrollregion', "0 0 #@last_x #$height")
  end
end

# 1st line is the signal name 
signal = gets
view = WViewer.new(signal)
# now plot points from stdin 
while gets
  dt, b = split
  view.plot_bit(dt.to_i, b.to_i)
end
# set scroll area
view.set_scrarea

Tk.mainloop