↓↓クリックして頂けると励みになります。
【45 | テキストコンポーネントの応用】 << 【ホーム】 >> 【47 | JTable】
断層化されたデータを表示するような場合にはツリーを利用すると便利です。
ツリーを実現するためのコンポーネントはjavax.swing.JTreeですが、JTreeを処理するためのクラスとインターフェイスはjavax.swing.treeパッケージになります。
treeパッケージにはツリーの表示に関する情報や内容が編集されたときの動作、内容がある場所の情報、ツリーデータのモデルなどが定義されています。
java.lang.Object +--java.awt.Component +--java.awt.Container +--javax.swing.JComponent +--javax.swing.JTree
ツリーは「ノード」と呼ばれる内容からなっています。
ノードは子ノードを持つ「ブランチ(branch)・ノード」と子ノードを持たない「リーフ(leaf)・ノード」と分けることが出来ます。
また一番もとになるノードは「ルート(root)・ノード」と呼ばれます。
以下のようなツリーを生成すると「Colors」「Sports」「food」というブランチ・ノードを持ったツリーが生成されます。
JTree tree = new JTree(); //サンプルモデルを持つツリーの生成
始めから自分でノードを定義してツリーを生成する場合にはjavax.swing.treeパッケージのDefaultMutableTreeNodeクラスを使用してノードを作っていき、それらのノードをもとにツリーを生成します。
DefaultMutableTreeNodeはjavax.swing.tree.MutableTreeNodeインターフェイスなどを実装しています。
MutableTreeNodeはjavax.swing.tree.TreeNodeインターフェイスを拡張したもので、ノードの挿入や削除、親子間の関係などを定義する場合に使用します。
ノードに子ノードを追加する場合は「add(MutableTreeNode)」メソッドを用います。
//ノードの生成 DefaultMutableTreeNode root = new DefaultMutableTreeNode("根"); DefaultMutableTreeNode branch = new DefaultMutableTreeNode("枝"); DefaultMutableTreeNode leaf = new DefaultMutableTreeNode("葉"); //ノードに子を追加 root.add(branch); branch.add(leaf); //「root」ノードを元にツリーを生成 JTree tree = new JTree(root);
ツリーモデルを使用することでノードの情報取得や追加や削除などの他にも、ツリーの情報が変更された場合の通知なども可能になります。
javax.swing.treeパッケージには、TreeModelインターフェイスを実装したDefaultTreeModelクラスが用意されています。
先のノード生成とあわせて使用すると良いでしょう。
//ノード生成 DefaultMutableTreeNode root = new DefaultMutableTreeNode("根"); DefaultMutableTreeNode branch = new DefaultMutableTreeNode("枝"); DefaultMutableTreeNode leaf = new DefaultMutableTreeNode("葉"); //ノードに子を追加 root.add(branch); branch.add(leaf); //ノードからツリーモデルを生成 DefaultTreeModel model = new DefaultTreeModel((TreeNode)root); //ツリーモデルを元にツリーを生成 JTree tree = new JTree(model);
JTreeクラスの「setEditable(boolean)」を用いることで、ノードの編集の可否を決めることが出来ます。
JTree tree = new JTree(); tree.setEditable(true); //ノードの編集可
編集は「トリプルクリック」あるいは「休止をはさんでマウスクリック2回→1200ミリ秒待つ」で始まります。
ツリーで発行されるイベントを取得する手段のひとつとして、マウスイベントを利用する方法があります。
マウスボタンがクリックされた(一番近い)場所からノードを取得することが出来ます。
public class Sample implements MouseListener { JTree tree; public JTreeTest4() { tree = new JTree(); tree.addMouseListener(this); //ツリーにマウスイベント追加 } /** マウスが押されたときの処理 */ public void mousePressed(MouseEvent evt) { //クリックされたノードの行数取得 int selectRow = tree.getRowForLocation(evt.getX(), evt.getY()); //クリックされたノードのパス取得 TreePath selectPath = tree.getPathForLocation(evt.getX(), evt.getY()); //選択されているノードがある場合処理 if (selectRow != -1) { //クリックされたノード名 String selectName = selectPath.getLastPathComponent().toString(); } } /** マウスリスナーを用いたときに必須なメソッド(内容はなし)*/ public void mouseClicked(MouseEvent evt) { } public void mouseReleased(MouseEvent evt) { } public void mouseEntered(MouseEvent evt) { } public void mouseExited(MouseEvent evt) { } }
ツリー内の座標を元に「getRowForLocation()
」(行数取得)、「getPathForLocation()
」(パス取得)などで、クリックされた場所(ノード)を判別することが出来ます。
またjavax.swing.eventパッケージに定義されているリスナやイベントを用いることで、以下のような情報の取得も出来ます。
リスナ | イベント | 内容 |
---|---|---|
TreeExpansionListener | TreeExpansionEvent | ツリーがノードの展開や収納を行った |
TreeModelListener | TreeModelEvent | ノードの挿入や削除があった |
TreeSelectionListener | TreeSelectionEvent | 選択範囲が変更された |
TreeWillExpandListener | TreeExpansionEvent | ツリーがノードの展開や収納を行った(実際に行う前に通知) |
ノードの追加は現在のノードを取得した上でそのノードに追加します。
また追加された情報を表示に反映させるにはjavax.swing.tree.TreePathクラスを用いて、再度パスを構築しなおすことが必要です。
追加の一例を示します。
「model」はツリーモデルのインスタンスとします。
//現在選択されているパスを取得 DefaultMutableTreeNode tn = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent(); //追加ノード作成 DefaultMutableTreeNode nn = new DefaultMutableTreeNode("新ノード"); //選択されているノードの子ノードとしてモデルに追加 model.insertNodeInto(n, tn, tn.getChildCount()); //ルートノードからの道筋を取得 TreeNode[] nodes = model.getPathToRoot(nn); //ツリーパスを再生成 TreePath path = new TreePath(nodes); //選択されたノードが見えるように設定(treeはJTreeのインスタンスとする) tree.scrollPathToVisible(path);
削除についても方法はいくつかありますが、下記はツリーモデルのメソッドを利用して親ノードからノードを削除します。
//現在選択されているパスを取得 DefaultMutableTreeNode tn = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent(); //親ノードから削除(modelはDefaultTreeModelのインスタンス) model.removeNodeFromParent(tn);
Visual Studio Codeで以下のプログラムを作成してください。
新規作成 【SwingJTreeTest1.java】
/**JTreeのテスト(初期設定のツリーの表示とスクロールとノード名編集の付加)*/ import javax.swing.*; public class SwingJTreeTest1 { private JTree tree; private JScrollPane sp; /**コンストラクタ*/ public SwingJTreeTest1(){ tree = new JTree(); //サンプルモデルを持つツリーを生成 tree.setEditable(false); //ノード名編集不可 sp = new JScrollPane(tree); //スクロールペインに配置 } /**main() */ public static void main(String[] args){ SwingJTreeTest1 tree = new SwingJTreeTest1(); JFrame frame = new JFrame("JTreeTest1"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(200,200); frame.getContentPane().add(tree.sp,"Center"); frame.setVisible(true); } }
実行するとツリー構造が表示されます。
フォルダをクリックすると内容が表示されます。
ノード名の変更は出来ません。
~/Desktop/Programming/JP $ javac SwingJTreeTest1.java ~/Desktop/Programming/JP $ java SwingJTreeTest1
Visual Studio Codeで以下のプログラムを作成します。
新規作成 【SwingJTreeTest2.java】
import javax.swing.*; public class SwingJTreeTest2 { private JTree tree; private JScrollPane sp; /**コンストラクタ*/ public SwingJTreeTest2(){ tree = new JTree(); //サンプルモデルを持つツリーを生成 tree.setEditable(true); //ノード名編集可 sp = new JScrollPane(tree); //スクロールペインに配置 } /**main() */ public static void main(String[] args){ SwingJTreeTest2 tree = new SwingJTreeTest2(); JFrame frame = new JFrame("JTreeTest2"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(200,200); frame.getContentPane().add(tree.sp,"Center"); frame.setVisible(true); } }
実行するとツリー構造が表示されます。
フォルダをクリックすると内容が表示されます。
ノード名の変更ができます。
編集は「トリプルクリック」あるいは「休止をはさんでマウスクリック2回→1200ミリ秒待つ」で始まります。
~/Desktop/Programming/JP $ javac SwingJTreeTest2.java ~/Desktop/Programming/JP $ java SwingJTreeTest2
Visual Studio Codeで以下のプログラムを作成します。
新規作成 【SwingJTreeTest3.java】
/**JTreeのテスト(自分でノードを作成する)*/ import javax.swing.*; import javax.swing.tree.*; //ノードを作成するために必要 public class SwingJTreeTest3 { private JTree tree; private JScrollPane sp; /**コンストラクタ*/ public SwingJTreeTest3(){ //ルート(一番上)ノード DefaultMutableTreeNode root = new DefaultMutableTreeNode("food"); //ルートノードへの追加 DefaultMutableTreeNode fruit = new DefaultMutableTreeNode("fruit"); //ルートノードへの追加 DefaultMutableTreeNode vegetable = new DefaultMutableTreeNode("vegetable"); root.add(fruit); root.add(vegetable); //「fruit」ノードへの追加 DefaultMutableTreeNode apple = new DefaultMutableTreeNode("apple"); DefaultMutableTreeNode orange = new DefaultMutableTreeNode("orange"); fruit.add(apple); fruit.add(orange); //「vegetable」ノードへの追加 DefaultMutableTreeNode lettuce = new DefaultMutableTreeNode("lettuce"); DefaultMutableTreeNode tomato = new DefaultMutableTreeNode("tomato"); vegetable.add(lettuce); vegetable.add(tomato); //ノードからツリーを生成 tree = new JTree(root); sp = new JScrollPane(tree); //スクロールペインに配置 } /**main() */ public static void main(String[] args){ SwingJTreeTest3 tree = new SwingJTreeTest3(); JFrame frame = new JFrame("JTreeTest3"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(200,200); frame.getContentPane().add(tree.sp,"Center"); frame.setVisible(true); } }
実行するとツリー構造が表示されます。
ノードの配置を自由に決めることができます。
ソースに追加することで好きな配置でノードを作成できます。
ノード名の編集は出来ません。
~/Desktop/Programming/JP $ javac SwingJTreeTest3.java ~/Desktop/Programming/JP $ java SwingJTreeTest3
Visual Studio Codeで以下のプログラムを作成します。
新規作成 【SwingJTreeTest4.java】
/**JTreeのテスト(モデルからの作成とイベント処理)*/ import java.awt.event.*; import javax.swing.*; import javax.swing.tree.*; //ノードを作成するために必要 public class SwingJTreeTest4 implements ActionListener, MouseListener { private JTree tree; private JScrollPane sp; private DefaultTreeModel model; private JPanel editPanel; private JLabel infoLabel; /**コンストラクタ*/ public SwingJTreeTest4(){ //パネルに「追加」「削除」ボタンを配置 editPanel = new JPanel(); JButton addButton = new JButton("Add"); JButton removeButton = new JButton("Remove"); editPanel.add(addButton); editPanel.add(removeButton); //マウスクリック時の情報を表示 infoLabel = new JLabel(" "); //ルート(一番上)ノード DefaultMutableTreeNode root = new DefaultMutableTreeNode("food"); //ルートノードへの追加 DefaultMutableTreeNode fruit = new DefaultMutableTreeNode("fruit"); //ルートノードへの追加 DefaultMutableTreeNode vegetable = new DefaultMutableTreeNode("vegetable"); root.add(fruit); root.add(vegetable); //「fruit」ノードへの追加 DefaultMutableTreeNode apple = new DefaultMutableTreeNode("apple"); DefaultMutableTreeNode orange = new DefaultMutableTreeNode("orange"); fruit.add(apple); fruit.add(orange); //「vegetable」ノードへの追加 DefaultMutableTreeNode lettuce = new DefaultMutableTreeNode("lettuce"); DefaultMutableTreeNode tomato = new DefaultMutableTreeNode("tomato"); vegetable.add(lettuce); vegetable.add(tomato); //ノードからモデルを生成 model = new DefaultTreeModel((TreeNode)root); //モデルからツリーを生成 tree = new JTree(model); tree.setEditable(true); //編集可 sp = new JScrollPane(tree); //スクロールペインに配置 //ボタンにイベント登録 addButton.addActionListener(this); removeButton.addActionListener(this); //ツリーにマウスイベント登録 tree.addMouseListener(this); } /**ボタンを押した時の処理*/ public void actionPerformed(ActionEvent evt){ DefaultMutableTreeNode tn = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent(); String command = evt.getActionCommand(); //ノードが選択されている時に処理を行う if(tn != null) { //追加ボタンを押した時の処理 if(command.equals("Add")) { //追加ノード作成 DefaultMutableTreeNode nn = new DefaultMutableTreeNode("new Node"); //選択されているノードの子ノードとして追加 model.insertNodeInto(nn, tn, tn.getChildCount()); //ルートノードからの道筋を取得 TreeNode[] nodes = model.getPathToRoot(nn); //ツリーパスを再生成 TreePath path = new TreePath(nodes); //選択されたノードが見えるように設定 tree.scrollPathToVisible(path); } else if (command.equals("Remove")) { //削除ボタン時 //ルートノードは削除しない if(tn.getParent() != null) { model.removeNodeFromParent(tn); //親ノードから削除 } } } } /**マウスが押された時の処理*/ public void mousePressed(MouseEvent evt) { //クリックされたノードの行数取得 int selectRow = tree.getRowForLocation(evt.getX(), evt.getY()); //クリックされたノードのパス取得 TreePath selectPath = tree.getPathForLocation(evt.getX(), evt.getY()); //選択されているノードがある場合の処理 if(selectRow != -1) { //クリックされたノード名 String selectName = selectPath.getLastPathComponent().toString(); //ダブルクリックの時だけの処理 if(evt.getClickCount() == 2) { //ラベルに情報を表示 infoLabel.setText("Row=" + selectRow + "Path=" + selectPath + "Name=" + selectName); } } } /**マウスリスナーを用いた時に必須なメソッド(今回は内容無し)*/ public void mouseClicked(MouseEvent evt) { } public void mouseReleased(MouseEvent evt) { } public void mouseEntered(MouseEvent evt) { } public void mouseExited(MouseEvent evt) { } /**main()*/ public static void main(String[] args){ SwingJTreeTest4 tree = new SwingJTreeTest4(); JFrame frame = new JFrame("JTreeTest4"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(400,200); //上から「ノード編集」「ツリー」「ノード情報」を配置 frame.getContentPane().add(tree.editPanel,"North"); frame.getContentPane().add(tree.sp,"Center"); frame.getContentPane().add(tree.infoLabel,"South"); frame.setVisible(true); } }
実行するとツリー構造が表示されます。
ノードをボタンひとつで自由に追加、削除出来ます。
ノード名の変更ができます。
編集は「トリプルクリック」あるいは「休止をはさんでマウスクリック2回→1200ミリ秒待つ」で始まります。
~/Desktop/Programming/JP $ javac SwingJTreeTest4.java ~/Desktop/Programming/JP $ java SwingJTreeTest4
【45 | テキストコンポーネントの応用】 << 【ホーム】 >> 【47 | JTable】
↓↓クリックして頂けると励みになります。