LoginSignup
0
1

More than 5 years have passed since last update.

textウィジェットのtagをプレースホルダとして使ってみた。

Posted at

シリアル通信で送受信したデータをtextウィジェットでバイナリエディタ風に

31 32 33 34 35 36 37 38 01 02 03 04 05 06 07 8a | 12345678........
42 43 44 61 62 63 64                            | BCDabcd         

みたいに逐次追加で表示しようとしている時にtagを使ってみたので、そのメモ。

最初、『詳解Tcl/Tk GUIプログラミング』を参考に、textを2つとscrollbarを1つを横並びに配置して、一方に16進数、他方にASCII文字を追記しつつ、1つのscrollbarで両方のtextを同時スクロールするように作り初めたけど、scrollbar絡みのカラクリを理解しきれず訳が分からなくなってしまって挫折しました。

そこでtextとscrollbarはオーソドックスな1:1の関係のままとして、tagをプレースホルダ的に使う方法を考えてみました。

まずtextに16バイト分の空欄を作ります。この時、16進数表示用プレースホルダとしてHEX0, HEX1, ... HEX14, HEX15というtagを、ASCII表示用プレースホルダとしてASCII0, ASCII1, ... ASCII14, ASCII15というtagを付与しておきます。

# $window is path name of the text widget.
for {set i 0} {$i < 16} {incr i} {
    $window insert end "  " HEX$i
    $window insert end " "
}
$window insert end "| "
for {set i 0} {$i < 16} {incr i} {
    $window insert end " " ASCII$i
}
$window insert end "\n"

そして以下のように1バイトづつ追記していくと、いい感じに表示が更新されました。

# $window is path name of the text widget.
# $lenght is number of shown data.
# $byte is new data.
set column [expr {$length % 16}]
incr length
binary scan $byte H2 hex
$window replace {*}[$window tag range HEX$column] $hex
if {[string is print $byte]} {
    set ascii $byte
} else {
    set ascii "."
}
$window replace {*}[$window tag range ASCII$column] $ascii

ここで意外だったのが、replaceでHEX1というtag範囲を置換するとHEX1というtagは範囲を失う(tagとしては存在し続ける)という挙動でした。

今回は別に実害は無いんですが、(labelウィジェットの-textvariableのように)何度も更新する値のためのプレースホルダとして利用したい場合はreplaceコマンドの引数でtagを再定義する必要がありそうです。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1