Create  Edit  Diff  Phillro Industries  Index  Search  Changes  History  Source  RSS  Note  wikifarm  Login

tut-tut_treeview

Author: NISHIO Mizuho

ツリービュー

IEのお気に入りやMozillaのブックマークのような木構造を表すためのコントロールです。

その1

$(Apollo)/sample/tutorial/treeview1.rb

   1|require 'phi'
   2|
   3|form = Phi::Form.new(:form1, 'フォームです')
   4|edit = Phi::Edit.new(form, :edit1, '')
   5|edit.align = Phi::AL_BOTTOM
   6|treeview = Phi::TreeView.new(form, :treeview1, '')
   7|treeview.align = Phi::AL_CLIENT
   8|nodes = treeview.items
   9|
  10|nodes.add(nil, '1')
  11|nodes.add(nil, '2')
  12|child_node = nodes.add(nil, '3')
  13|
  14|nodes.add_child(child_node, '3-1')
  15|nodes.add_child(child_node, '3-2')
  16|nodes.add_child(child_node, '3-3')
  17|
  18|treeview.on_click = proc do
  19|  unless treeview.selected.nil?
  20|    edit.text = treeview.selected.text
  21|  end
  22|end
  23|
  24|form.show
  25|Phi.mainloop

このスクリプトを実行すると、このような ウィンドウがあらわれます。

解説

6行目がツリービューを生成しているところです。 Phi::TreeView.new の使い方はいつもと同じです。

8行目で treeview.items( Phi::TreeView#items ) を nodes に代入しています。 Phi::TreeView#items はツリービューの項目全体を表すオブジェクト( Phi::TreeNodes? )で、これを使うことでツリーの項目を操作することができます。このスクリプトでは何回も Phi::TreeNodes? のオブジェクトを使うので、nodes に代入して簡単に参照できるようにしています。

10〜12行はnodes.addを使ってツリーの一番上に「1」「2」「3」の項目を追加しています。nodes.add( http://otwvwb.com/ )の第1引数を nil にすることで、ツリーの一番上の部分に項目が追加され、第2引数によって追加された項目の文字列が設定されます。

14〜16行はツリーの「3」の項目に「3-1」「3-2」「3-3」の項目を追加しています。nodes.add_child( Phi::TreeNodes#add_child )は子ノード(子の項目)を追加するためのメソッドで、第1引数には親ノード( Phi::TreeNode? のオブジェクト ) を、第2引数は子ノードに表示する文字列を指定します。

18〜22行はツリービューをクリックした時のイベントハンドラです。 Phi::TreeView#on_click が何に使われるかはすぐ分かりますよね。 treeview.selected( Phi::TreeView#selected )は現在選択されている項目(ノード)を表す属性なので、19行の treeview.selected.nil? は選択されている項目がある時に true を返します。20行は選択された項目の文字列をエディットに表示させます。この行で使われている Phi::TreeNode#text は項目の文字列を得るための属性です。

クラスやメソッド

Phi::ListView

Phi::TreeNodes

Phi::TreeNode

その2

$(Apollo)/sample/tutorial/treeview2.rb

   1|require 'phi'
   2|require 'find'
   3|require 'dialogs'
   4|
   5|form = Phi::Form.new(:form1, 'フォームです')
   6|form.height = 400
   7|
   8|panel = Phi::Panel.new(form, :form1, '')
   9|panel.align = Phi::AL_TOP
  10|panel.height = 24
  11|button = Phi::Button.new(panel, :button1, 'フォルダ選択')
  12|button.align = Phi::AL_RIGHT
  13|button.width = 100
  14|edit = Phi::Edit.new(panel, :edit1, '')
  15|edit.align = Phi::AL_CLIENT
  16|edit.width = panel.width - button.width
  17|edit.text = 'd:/docu/document/apollo'
  18|
  19|show_btn = Phi::Button.new(form, :show_btn1, '表示')
  20|show_btn.align = Phi::AL_BOTTOM
  21|
  22|treeview = Phi::TreeView.new(form, :treeview1, '')
  23|treeview.align = Phi::AL_CLIENT
  24|nodes = treeview.items
  25|
  26|button.on_click = proc do 
  27|  result_path = ''
  28|  if Phi::select_dir('フォルダーを選択してください', '/', result_path)
  29|    edit.text = result_path
  30|    form.set_focus
  31|  end
  32|end
  33|
  34|show_btn.on_click = proc do
  35|  if edit.text != '' and FileTest::directory?(edit.text)
  36|    nodes.clear
  37|    nodes.update {
  38|      path = File::expand_path(edit.text)
  39|      dir = {}
  40|      top_node = nodes.add(nil, File::dirname(path))
  41|      dir[File::dirname(path)] = top_node
  42|      Find::find(edit.text) do |f|
  43|  dirname = File::dirname(f)
  44|  node = nodes.add_child(dir[dirname], File::basename(f))
  45|  if FileTest::directory?(f)
  46|    dir[f] = node
  47|  end
  48|      end
  49|    }
  50|  else
  51|    Phi::message_dlg(edit.text + ' はフォルダーではありません。', 
  52|         Phi::MT_ERROR, [Phi::MB_OK], 0)
  53|  end
  54|end
  55|
  56|form.show
  57|Phi.mainloop

このスクリプトを実行すると、このような ウィンドウがあらわれます。

解説

このスクリプトは Ruby/GTKチュートリアル のTreeウィジェットの章で紹介されているスクリプトを Apollo に移植したものです(少し手を入れています)。このスクリプトでは指定されたフォルダの一つ上のフォルダをツリーのトップにして、その下にあるファイルやフォルダをツリー状に表示することができます。このスクリプトは少し難しいので、Rubyに馴れていない人はFindのモジュールを使った他のRubyスクリプトを読んでから、このスクリプトを読んだ方が良いかもしれません。

2行目はRubyに標準添付されているFindモジュールを使うためのおまじないです。

8行目は Phi::Panel のオブジェクトを生成しています。これはウィンドウの上の方にある ボタンとエディットをまとめている部分です。このスクリプトではボタンとエディットでパネルの部分を完全に覆っているので、パネルを見ることはできません。

8〜24行は分かると思います。

26〜32行は画面の上にある「フォルダ選択」ボタンが押された時のイベントハンドラを設定しています。28行目の Phi::select_dir はディレクトリ選択のダイアログを表示させるためのメソッドです。ディレクトリ選択のダイアログの図

図を見てもらえば分かりますが、Phi::select_dirの第1引数はダイアログに表示される文字列を表しています。第2引数はダイアログに表示される一番上のフォルダーを指定します。これは '/' から変更する必要はないと思います。最後の第3引数にはユーザーが選択したフォルダのパスが代入される変数が入ります。27行で result_path を初期化しているのはこのためです。 Phi::select_dir はダイアログの「OK」ボタンを押した時にtrueになります。

28行で Phi::select_dir の返り値がtrueの場合、29行によってユーザーが選択したフォルダのパスがエディットに設定され、フォーカスがフォームに合わせられます。

34〜54行は「フォルダーを選択してください」のボタンが押されたときのイベントハンドラです。35行はエディットの文字列が適切なものかどうか調べています。エディットの文字列が適切なものでない場合は51〜53行が実行されてメッセージダイアログが表示されます。一方、エディットの文字列が適切な場合は、36〜49行が実行されます。

36行は nodes.clear( Phi::TreeNodes#clear )によって今までツリーに表示されていた項目がすべて消去されます。

37行の nodes.update( Phi::TreeNodes#update )は{}に囲われた部分(今回の場合は38〜48行)がすべて実行されるまで画面描画を抑制するために使われます。

例えば、 Phi::TreeNodes#update を使わずに100単位の項目をツリーに追加すると、項目を追加する度に画面が描画されるため項目の追加が非常に遅くなります。これを防ぐのが Phi::TreeNodes#update です。

Delphiの TTreeNodes?.BeginUpdate? と TTreeNodes?.EndUpdate? に当たるメソッドが Phi::TreeNodes#update になるので、Delphiを使っている人は注意してください。

38行ではエディットの文字列を Phi::expand_path を使ってフルパスに変換し、path に代入します。40行では nodes.add によって一番上のノードが追加されます。ここではエディットで指定されたパス名より一つ上のフォルダが追加されます。41行ではパス名が鍵、値が最上位のノード( Phi::TreeNode? のオブジェクト )となるように Hash のオブジェクトに値をセットしています。

42行はFindモジュールのfindメソッドを使っています。 Find::find ではイテレーターが使われていて、Find::find の引数となるフォルダを探索し、指定されたフォルダの下にあるファイル名が順に f に代入されます。例えば、下のスクリプトでは 「d:/docu/document」 の下にあるすべてのファイルが標準出力に表示されます。

require 'find'

Find::find('d:/docu/document') do |f|
  print f
end

43行でfのファイル名をフォルダー名とベース名に分離し、44行で項目を追加しています。ここの第1引数が何故 dir[dirname] になるのかについては考えてみてください。46行は f がフォルダーの時に実行され、dir に新しい鍵と値の関係がセットされます。

クラスやメソッド

Rubyの組み込みモジュール

  • FileTest?

Rubyに標準添付されているモジュール

  • Find

Rubyの組み込みクラス

  • File

Phi

  • Phi::select_dir

Phi::Panel

  • Phi::Panel.new

Phi::TreeNodes

Last modified:2004/11/26 06:08:35
Keyword(s):
References:[Phi::TreeNode] [Phi::TreeNodes] [Phi::TreeView] [tut-tut_index]