今回はTTreeViewコンポーネントについて紹介します。
他のコンポーネントと違って感覚的に使用しにくいものの、
一度使い方を理解できれば難しくありません。
まだ使用したことのない方は、この機会に挑戦してみてください。
TTreeViewコンポーネントは、Explorerの左ペインのように
階層構造を視覚的にわかりやすく表示できる機能を実装するコンポーネントです。
通常Explorerなどではフォルダやドライブが表示されていますが、これらをTTreeViewでは「ノード」と呼んでいます。
これらは階層構造になっていますが、この深さを「レベル」という単位で表します。
レベルが0で一番上のノード、数が多くなるに従ってそのレベルの数は多くなっていきます。
これらのノードの情報はTTreeViewではItemsプロパティで保持しています。
このItemsプロパティにノードを足していく事で、階層構造を形作るようになっています。
基本編
トップノードを追加する
Itemsプロパティにノードを足していく方法は大きく分けて2つあります。
一番上(レベル0)のトップノードを足す方法と、
二番目以降(レベル1以上)のノードを足す方法です。
まずはトップノードをロジックで追加する方法をご説明します。
次のような画面を作成します。
TTreeViewコンポーネントはWin32パレット内に存在します。

[最初に追加]ボタンのOnClickイベントで次のようにコードを記述します。
Itemsプロパティは、表示される個々のノードをリストします。
AddFirstメソッドは、指定したノードの兄弟ノードとして最初に追加されます。
指定するノードを「nil」にすると、最初のレベルの先頭にノードが追加されます。
// 最初に追加
procedure TForm1.Button1Click(Sender: TObject);
begin
TreeView1.Items.AddFirst(nil, Edit1.Text);
end;
実行すると、Editに指定した値で先頭にノードが追加されます。

[最後に追加]ボタンのOnClickイベントで次のようにコードを記述します。
Addメソッドは、指定したノードの兄弟ノードとして最後に追加されます。
指定するノードを「nil」にすると、最初のレベルの最後にノードが追加されます。
// 最後に追加
procedure TForm1.Button2Click(Sender: TObject);
begin
TreeView1.Items.Add(nil, Edit1.Text);
end;
実行すると、Editに指定した値で最後にノードが追加されます。

サブノードを追加する
ノードの下の階層項目をサブノードといいます。
選択したノードにサブノードを追加する方法をご説明します。
[追加]ボタンのOnClickイベントで次のようにコードを記述します。
AddChildメソッドは、指定したノードの子ノードとして最後に追加されます。
ここでは指定するノードは画面のTreeViewで選択したもの(Selectedプロパティ)です。
これで、選択したノードの子ノードとして追加されます。
また追加したノードを確認しやすいようにするため、親ノードを展開しています。
procedure TForm1.Button3Click(Sender: TObject);
var
trnd: TTreeNode;
begin
// 選択されたノードがない場合,Selected の値は nil
if TreeView1.Selected <> nil then
begin
TreeView1.Items.AddChild(TreeView1.Selected, Edit2.Text);
// 親ノードを展開
TreeView1.Selected.Expanded := True;
end
else
begin
ShowMessage('ノードが選択されていません。');
end;
end;
上のコードでも分かるとおり、引数はそれぞれ2つ必要です。
1つ目が兄弟のノードを示します。2つ目は追加する文字列です。
兄弟とはまさしく同じ親を持つノードのことです。
レベル0のノードは親がありませんから、全てのレベル0のノードは兄弟になります。
AddFirstでは基本的に兄弟は指定しません。
また、一番最初に追加する場合も指定しようがありませんので第1引数はnilになります。
実行すると、Editに指定した値で選択したノードの下にサブノードが追加されます。

選択しているノードの情報を取得する
ノードは項目値を始め、各情報を持ちます。
TreeViewのOnClickイベントで次のようにコードを記述します。
Selectedプロパティは、選択したノードを表します。
procedure TForm1.TreeView1Click(Sender: TObject);
begin
// 選択されたノードがない場合,Selected の値は nil
if TreeView1.Selected <> nil then
Edit3.Text := TreeView1.Selected.Text;
end;
実行すると、選択したノードのTextをEditに表示します。

Selectedプロパティのようにノードを表すものはTTreeNodeオブジェクトです。
これは次の代表的なプロパティを持ちます。
| プロパティ | 内容 |
|---|---|
| HasChild | 子ノードを持つ場合、Trueとなります。 |
| Count | ノードにある子ノードの数を表します。 |
| Item | 子ノードにアクセスできます。最初の子ノードはItem[0]、2番目はItem[1]です。 |
| Level | トップノードのLevel値は 0 です。その子のLevel値は 1 になります。 |
| Parent | 親ノードにアクセスできます。 |
詳しくはDelphiのヘルプでTTreeNodeをご参照下さい。
ノードを削除する
ノードを削除するにはDeleteメソッドを使用します。
[削除]ボタンのOnClickイベントで次のようにコードを記述します。
Deleteメソッドは、指定したノードを削除します。
procedure TForm1.Button4Click(Sender: TObject);
begin
if TreeView1.Selected <> nil then
TreeView1.Selected.Delete
else
ShowMessage('ノードが選択されていません。');
end;
実行すると、選択したノードが削除されます。
親ノードを削除した場合、その下の子ノードもすべて削除されます。

発展編
全ノードを展開/縮小する
全ノードを展開/縮小するためのメソッドがあります。
ボタンを3つ追加します。

[全てのノードを展開][全てのノードを縮小]のボタンのOnClickイベントで次のようにコードを記述します。
procedure TForm1.Button5Click(Sender: TObject);
begin
// 全てのノードを展開
TreeView1.FullExpand;
end;
procedure TForm1.Button6Click(Sender: TObject);
begin
// 全てのノードを縮小
TreeView1.FullCollapse;
end;
実行すると、ノードがすべて展開/すべて縮小されます。

全てのノードを削除する
全ノードを消去するには、ItemsのClearメソッドで実行します。
[全てのノードを消去]ボタンのOnClickイベントで次のようにコードを記述します。
procedure TForm1.Button6Click(Sender: TObject);
begin
// 全てのノードを消去
TreeView1.Items.Clear;
end;
実行すると、ノードがすべて削除されて空になります。

リストの読み込みと保存
LoadFromFile:ファイルから読み込みます。引数は読込むファイルのパスです。
SaveToFile:ファイルへ保存します。引数は保存先ファイルのパスです。
これらはTStringsクラスに実装されているメソッドと同じように使えます。
通常ファイルを使用する場合はこれらのメソッドを使用すると便利ですが、
Streamを使用する場合はLoadFromStream、SaveToStreamを使用されてもいいでしょう。
// ノード情報を保存する例
TreeView1.SaveToFile('C:\Support\07_WP_tips\M014\nodes13.txt');
// ノード情報を読み込む例
TreeView1.LoadFromFile('C:\Support\07_WP_tips\M014\nodes13.txt');

ノードをドラッグ&ドロップで移動する
ドラッグ処理とドロップ処理でコード記述が必要です。
TreeViewのDragModeプロパティをdmAutomaticにします。
TreeView1のOnDragOverイベントとOnDragDropイベントで次のようにコードを記述します。
今回はドロップ先の子ノードとして追加しています。
procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
// ドラッグ処理
Accept:=False;
if Source is TTreeView then
if TreeView1.GetNodeAt(X,Y) <> nil then
Accept:=True;
end;
procedure TForm1.TreeView1DragDrop(Sender, Source: TObject; X,Y: Integer);
var
DropNode : TTreeNode;
begin
// ドロップ処理
DropNode := TreeView1.GetNodeAt(X, Y);
if DropNode <> nil then
TreeView1.Selected.MoveTo(DropNode,naAddChild);
end;
実行すると、ノードをドラッグ&ドロップで移動することができます。
親ノードをドラッグした場合、配下の子ノードもこのロジックで移動できます。

参考リンク
- Vcl.ComCtrls.TTreeView – RAD Studio API Documentation(エンバカデロ Docwiki)
- Vcl.ComCtrls.TTreeNode – RAD Studio API Documentation(エンバカデロ Docwiki)
(構成:ミガロ.情報マガジン「MIGARO News!!」Vol.014 2002年3月号より)
(コーディング:旧Tips Delphi/400 入門 Tips12~13「TreeViewの使用方法」より)