ちょっと前の話になりますが、 From: akaishi / ruby.freak.ne.jp Subject: [ruby-list:17956] Re: ruby-gtk の tree オブジェクトに関する質問 Date: Sat, 23 Oct 1999 19:36:40 +0900 > Gtk::Tree は children がすべて remove されると self まで destroy されて > しまうように見えます。そういう仕様? > > 対処療法としては children をすべて remove せずに最低一つ残しておいて、何 > か append してから remove する、でしょうか。 昔、ディレクトリツリーを表示するクラスを作ったことがあって、参考までに添 付します。一応ディレクトリの増減に追従するようにしてみました。expand す るときに更新します。unix 系専用。 -- akaishi Gtk::DirTree<Gtk::Tree, Gtk::DirTreeItem<Gtk::TreeItem ローカルなファイルシステムのディレクトリツリーを表示するためのウィジェッ ト。 使い方: dirtree = Gtk::DirTree.new # DirTree ウィジェット生成 rootitem = Gtk::DirTreeItem.new('/') # ルートとなる DirTreeItem 生成 # 引数はパス名 dirtree.append rootitem rootitem.show dirtree.show プログラム: require 'gtk' module Gtk class DirTreeItem < TreeItem attr_reader :path attr_writer :root def initialize(path) @path = path if path == '/' super '/' else if path[-1] == ?/ #/ path = path[0..-2] end super File.basename path end signal_connect('expand') { update_subtree } end def update_item if !@subtree and @root.walker.has_subdir?(path + '/') tree = Gtk::DirTree.new(@root) set_subtree tree end end def update_subtree newdirnames = @root.walker.find_dir(@path + '/').sort newdirsize = newdirnames.size del = [] @subtree.children.each_with_index {|olditem, ind| olddirname = File.basename(olditem.path) while newdirnames[0] and newdirnames[0] < olddirname if @path == '/' newpath = '/' + newdirnames[0] else newpath = @path + '/' + newdirnames[0] end item = Gtk::DirTreeItem.new(newpath) @subtree.insert item, ind item.show newdirnames.shift end if not newdirnames[0] or olddirname < newdirnames[0] del.push olditem else olditem.update_item newdirnames.shift end } newdirnames.each {|dirname| if @path == '/' newpath = '/' + dirname else newpath = @path + '/' + dirname end item = Gtk::DirTreeItem.new newpath @subtree.append item item.show } del.each {|item| @subtree.remove item} @subtree = nil if newdirsize == 0 end def set_subtree tree super tree @subtree = tree end def show super update_item end end class DirTree < Tree attr_accessor :walker def initialize root=nil, walker=nil super() if root @root = root else @root = self unless walker @walker = DirWalker.new end end end def append item super item.root = @root end def insert item, pos super item.root = @root end end class DirWalker attr_reader :cwd def initialize @cwd = Dir.getwd end def root '/' end def find_dir(path) path += '/' unless path[-1] == ?/ #/ res = [] Dir.foreach(path) {|f| if f != '.' and f != '..' and File.directory? path + f res.push f end } res end def has_subdir?(path) if File.stat(path).nlink == 2 false else true end end end end if $0 == __FILE__ window = Gtk::Window.new(Gtk::WINDOW_TOPLEVEL) swindow = Gtk::ScrolledWindow.new swindow.set_policy Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC dirtree = Gtk::DirTree.new rootitem = Gtk::DirTreeItem.new('/') dirtree.append rootitem rootitem.show dirtree.show swindow.add_with_viewport dirtree swindow.set_usize 200, 400 swindow.show window.add swindow window.show Gtk.main() end