2016-04-13

JavaFX: TreeView と CheckBoxTreeItem

JavaFX の TreeView にポップアップ・メニュー (ContextMenu) を表示するサンプルを以前紹介しましたが [1]、さらにチェックボックスをつける用途が出てきたので、まずは前述のサンプルをベースにテストをしました。まだ無駄が残っていますが、当初予定していた機能を実装できましたので紹介します。更に検討を加えた結果、補足・修正を加えるかもしれませんが、あらかじめご了承ください。

実行例

今回のサンプルは少々ソースが長くなるため、最初に実行例を示します。

にんじんのチェックボックスが 'false' から 'true' に変更されました。
なすのチェックボックスが 'false' から 'true' に変更されました。
とまとのチェックボックスが 'false' から 'true' に変更されました。
「とまと」が選択されました。

ソース

動作環境は次の通りです。

  • OS: Fedora 23 (x86_64)
  • Java: jdk1.8.0_77-1.8.0_77-fcs.x86_64 (Oracle)
  • IDE: NetBeans IDE 8.1
リスト:Sample_TreeView3.java 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package sample_treeview3;
 
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.CheckBoxTreeItem;
import javafx.scene.control.cell.CheckBoxTreeCell;
import static javafx.application.Application.launch;
 
public class Sample_TreeView3 extends Application {
 
    Image CAROT = new Image(getClass().getResource("carot.png").toString());
    Image EGGPLANT = new Image(getClass().getResource("eggplant.png").toString());
    Image TOMATO = new Image(getClass().getResource("tomato.png").toString());
    Image APPLE = new Image(getClass().getResource("apple.png").toString());
    Image GRAPE = new Image(getClass().getResource("grape.png").toString());
    Image BANANA = new Image(getClass().getResource("banana.png").toString());
 
    TreeView<String> tree;
 
    @Override
    public void start(Stage primaryStage) {
 
        TreeItem<String> top = new TreeItem<>("root");
 
        TreeItem<String> nodeItemA = new TreeItem<>("野菜");
        addNode(top, nodeItemA);
        nodeItemA.setExpanded(true);
        TreeItem<String> nodeItemB = new TreeItem<>("果物");
        addNode(top, nodeItemB);
        nodeItemB.setExpanded(true);
 
        TreeLeaf<String> nodeItemA1 = new TreeLeaf<>("にんじん", new ImageView(CAROT));
        TreeLeafListener(nodeItemA1);
        addNode(nodeItemA, nodeItemA1);
        TreeLeaf<String> nodeItemA2 = new TreeLeaf<>("なす", new ImageView(EGGPLANT));
        TreeLeafListener(nodeItemA2);
        addNode(nodeItemA, nodeItemA2);
        TreeLeaf<String> nodeItemA3 = new TreeLeaf<>("とまと", new ImageView(TOMATO));
        TreeLeafListener(nodeItemA3);
        addNode(nodeItemA, nodeItemA3);
 
        TreeLeaf<String> nodeItemB1 = new TreeLeaf<>("りんご", new ImageView(APPLE));
        TreeLeafListener(nodeItemB1);
        addNode(nodeItemB, nodeItemB1);
        TreeLeaf<String> nodeItemB2 = new TreeLeaf<>("ぶどう", new ImageView(GRAPE));
        TreeLeafListener(nodeItemB2);
        addNode(nodeItemB, nodeItemB2);
        TreeLeaf<String> nodeItemB3 = new TreeLeaf<>("ばなな", new ImageView(BANANA));
        TreeLeafListener(nodeItemB3);
        addNode(nodeItemB, nodeItemB3);
 
        tree = new TreeView<>(top);
        tree.setShowRoot(false);
        tree.setCellFactory((TreeView<String> p) -> new TreeCellImpl());
 
        StackPane root = new StackPane();
        root.getChildren().add(tree);
 
        Scene scene = new Scene(root, 200, 300);
 
        primaryStage.setTitle(getClass().getSimpleName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }
 
    void TreeLeafListener(TreeLeaf<String> item) {
        item.selectedProperty().addListener((ObservableValue<? extends Boolean> obs, Boolean oldVal, Boolean newVal) -> {
            System.out.println(item.getValue() + "のチェックボックスが '" + oldVal + "' から '" + newVal + "' に変更されました。");
        });
    }
 
    void addNode(TreeItem<String> parent, TreeItem<String> child) {
        parent.getChildren().add(child);
    }
 
    class TreeLeaf<T> extends CheckBoxTreeItem<T> {
 
        public TreeLeaf(final T value) {
            super(value);
        }
 
        public TreeLeaf(final T value, final Node graphic) {
            super(value, graphic);
        }
 
        public ContextMenu getMenu() {
            ContextMenu popup = new ContextMenu();
            MenuItem menuItem = new MenuItem("処理");
            menuItem.setOnAction((ActionEvent event) -> {
                TreeItem selItem = tree.getSelectionModel().getSelectedItem();
                System.out.println("「" + selItem.getValue() + "」が選択されました。");
            });
            popup.getItems().add(menuItem);
 
            return popup;
        }
    }
 
    public final class TreeCellImpl extends CheckBoxTreeCell<String> {
 
        @Override
        public void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
 
            if (empty) {
                setText(null);
                setGraphic(null);
            } else if (getTreeItem().getClass().toString().endsWith("TreeLeaf")) {
                setContextMenu(((TreeLeaf) getTreeItem()).getMenu());
            } else {
                setText(getItem() == null ? "" : getItem());
                setGraphic(getTreeItem().getGraphic());
            }
        }
    }
 
    public static void main(String[] args) {
        launch(args);
    }
}

参考サイト

  1. bitWalk's: JavaFX: TreeView と ContextMenu (2)

 

ブログランキング・にほんブログ村へ
にほんブログ村

0 件のコメント: