Tixのグリッド (3)

このページでは、先のサンプルでご紹介しきれなかった tixGrid のポイントを補足します。 というときにいつも出てくるのが、 テキストファイルからあのデータを読み込んで、 表示、編集できるサンプルです。 (このページのサンプルでは編集後の保存はできません)
まず、マスターデータとして、 下のようなタブ区切り形式のテキストファイルを作り、 "shiten.txt" の名前で保存します。

00100	札幌	1	札幌市清田区美しが丘九条9丁目99	30
00200	仙台	2	仙台市青葉区柏木9-9-99	32
00301	新宿	3	東京都新宿区新宿九丁目99−99	50
... (略) ...

Tclプログラムは以下の通りです。 ファイルの読み取りのために、 Standard Tcl Library(Tcllib)のfileutil、textutilパッケージを使っているので、 Tcllibをインストールしている必要があります。

package require Tix
package require fileutil
package require textutil

wm title . "Shiten"

# タブ区切りテキストファイルを読み、
# 中身を行、列2次元のリストに格納して返します。
proc readDataFile dataVar {
    upvar $dataVar data
    set content [::fileutil::cat "./shiten.txt" -encoding cp932]
    set rows [::textutil::split::splitx $content {[\r\n]+} ]
    set data {}
    foreach rowStr $rows {
        set rowArr [::textutil::split::splitx $rowStr "\\t+"]
        lappend data $rowArr
    }
}

# 各セルをフォーマットするコールバックプロシージャ
proc cbFormatCmd {w area x1 y1 x2 y2} {
    if {$area eq "main"} {
        $w format grid $x1 $y1 $x2 $y2 \
              -bd 2 -bordercolor #606060 -relief raised \
              -bg #eeeeee -fill 1
    }
    if {$area eq "x-margin"} {
        $w format grid $x1 $y1 $x2 $y2 \
              -bd 2 -bordercolor #606060 -relief raised \
              -bg #dddddd -fill 1
    }
}

# 編集を開始しようとする際に呼ばれるコールバックプロシージャ
set OriginalCopy {}
proc cbEditNotifyCmd {w x y} {
    global OriginalCopy
    if {$y == 0} {
        return 0
    } else {
        set curval [$w entrycget $x $y -text]
        if {"$curval" == "-"} {
            tk_messageBox -message "値が-のセルは編集できません。"
            return 0
        } else {
            set OriginalCopy $curval
            return 1
        }
    }
}

# 編集が完了する際に呼ばれるコールバックプロシージャ
proc cbEditDoneCmd {w x y} {
    global OriginalCopy
    set curval [$w entrycget $x $y -text]
    if {$x == 2 || $x == 4} {
        if {! [string is integer $curval]} {
            tk_messageBox -message "整数で入力してください。エラー:${curval}";
            $w entryconfigure $x $y -text $OriginalCopy
        }
    }
}

set f [frame .f]
set g [tixGrid $f.g -width 5 -height 6 \
       -font {Helvetica 12 normal} \
       -format "cbFormatCmd $f.g" \
       -leftmargin 0 -selectmode extended \
       -xscrollcommand "$f.scrh set" -yscrollcommand "$f.scrv set" \
       -editnotify "cbEditNotifyCmd $f.g" \
       -editdone "cbEditDoneCmd $f.g" ]
set scrv [scrollbar $f.scrv -ori v -com "$g yview"]
set scrh [scrollbar $f.scrh -ori h -com "$g xview"]
grid $g -row 0 -column 0
grid $scrv -row 0 -column 1 -sticky ns
grid $scrh -row 1 -column 0 -sticky ew

$g size col 0 -size 10char
$g size col 1 -size 10char
$g size col 2 -size 4char
$g size col 3 -size 32char
$g size col 4 -size 10char

set collabels {支店コード 支店名称 地域 所在地 従業員数}
set x 0
foreach e $collabels {
    $g set $x 0 -itemtype text -text $e ; incr x
}

readDataFile data

set y 1
foreach e $data {
    set x 0
    foreach c $e {
        $g set $x $y -itemtype text -text $c; incr x
    }
    incr y
}

button .b -text 終了 -command exit
pack $f .b -side top -anc e


縦の見出し列を表示しない

先の例では、横1行目、縦1列目がともに見出しのような扱いでしたが、 表形式としては縦1列目が見出しではなく、左端からいきなりデータで始まることも多いと思います。 その場合は -leftmargin を0にすればOKです。 このときは、formatコマンドのy-marginとs-marginに相当する場所はなくなります。 (左端がy-margin、上端がx-marginです。一瞬逆に考えてしまいがちなので要注意)
また、横の見出し行数を変更するには、-topmarginの値を変更します。


入力値の検証(バリデーション)

-editdonecmd でコールバックプロシージャを登録すると、 セルが編集された直後のタイミングで実行されるので、 編集されたセルの位置と新しい値を確認することができますが、 その変更を中止することはできません。
つまり-editdonecmdは、セルの編集は完了してしまったという前提で実行されるので、 入力値の検証(validation)のために実行するという位置づけではないもののようです。
しかし、上の例のように、-editnotifycmd のコールバックで編集前の値をグローバル変数に保存しておき、 -editdonecmdでNGだったらその値に上書きしてしまうことで、 汚いですが無理やり入力値の検証を実現することもできます。


ドキュメントされていない制約

これ以外に、どうもできないっぽい制約にいくつか気づきました。

  • format gridコマンドで指定できるオプションに背景色(-bg)はあるが、 文字色がない。(-foregroundオプションはない) つまり、文字の色は黒固定と思うしかないようです。
  • 編集モードになったときのフォントの設定方法が不明。
  • 選択した行が水色になるが、この色の変更方法が不明。

拡張レビュー分室 top
(first uploaded 2010/09/25 last updated 2010/09/25, MISUMI URANO)