前回、Tcl/Tk 8.5.0 で追加されたテーマ・ウィジェットを紹介しましたが、このテーマ・ウィジェット Ttk では、Tk にないウィジェットも利用できます。
ttk::treeview はそのうちのひとつです。 今回は、Tk のデモプログラムをベースに、単体で動作するように修正したサンプルを紹介します。このサンプルは、ルートディレクトリ以下のファイルの階層構造をツリー状に表示します。
#!/bin/sh
# the next line restarts using wish \
exec wish "$0" "$@"
# ----------------------------------------------------------------------------
# Code to populate the roots of the tree (can be more than one on Windows)
# ----------------------------------------------------------------------------
proc populateRoots {tree} {
foreach dir [lsort -dictionary [file volumes]] {
set node [$tree insert {} end -text $dir -values [list $dir directory]]
populateTree $tree $node
}
}
# ----------------------------------------------------------------------------
# Code to populate a node of the tree
# ----------------------------------------------------------------------------
proc populateTree {tree node} {
if {[$tree set $node type] ne "directory"} return
set path [$tree set $node fullpath]
$tree delete [$tree children $node]
foreach f [lsort -dictionary [glob -nocomplain -dir $path *]] {
set type [file type $f]
set id [$tree insert $node end \
-text [file tail $f] \
-values [list $f $type]]
if {$type eq "directory"} {
# Make it so that this node is openable
$tree insert $id 0 -text dummy ;# a dummy
$tree item $id -text [file tail $f]
} elseif {$type eq "file"} {
set size [file size $f]
# Format the file size nicely
if {$size >= 1024*1024*1024} {
set size [format %.1f\ GB [expr {$size/1024/1024/1024.}]]
} elseif {$size >= 1024*1024} {
set size [format %.1f\ MB [expr {$size/1024/1024.}]]
} elseif {$size >= 1024} {
set size [format %.1f\ kB [expr {$size/1024.}]]
} else {
append size " bytes"
}
$tree set $id size $size
}
}
# Stop this code from rerunning on the current node
$tree set $node type processedDirectory
}
# ----------------------------------------------------------------------------
# MAIN
# ----------------------------------------------------------------------------
wm title . "Directory Browser"
ttk::style theme use "clam"
# Create the tree and set it up
ttk::treeview .tree \
-columns {fullpath type size} \
-displaycolumns {size} \
-yscroll ".vsb set" \
-xscroll ".hsb set"
if {[tk windowingsystem] ne "aqua"} {
ttk::scrollbar .vsb -orient vertical -command ".tree yview"
ttk::scrollbar .hsb -orient horizontal -command ".tree xview"
} else {
scrollbar .vsb -orient vertical -command ".tree yview"
scrollbar .hsb -orient horizontal -command ".tree xview"
}
.tree heading \#0 -text "Directory Structure"
.tree heading size -text "File Size"
.tree column size -stretch 0 -width 70
populateRoots .tree
bind .tree <<TreeviewOpen>> {populateTree %W [%W focus]}
# Arrange the tree and its scrollbars in the toplevel
grid .tree -column 0 -row 0 -sticky news
grid .vsb -column 1 -row 0 -sticky ns
grid .hsb -column 0 -row 1 -sticky ew
grid columnconfigure . 0 -weight 1
grid rowconfigure . 0 -weight 1
# ---
# ttkwidget_treeview.tcl
Windows XP で実行した例
Fedora 8 (Linux) で実行した例
ちなみに階層構造を扱うウィジェットには、拡張パッケージ BWidget の Tree、Incr Widgets の hierarchy などが利用できます。