JTreeのTreeNodeが編集を開始可能かを調査する
Total: 709, Today: 1, Yesterday: 1
Posted by aterai at
Last-modified:
Summary
JTreeのノードエディタが編集を開始できるかどうかをTreePathやMouseEventから状態を取得して判断します。
Screenshot

Advertisement
Source Code Examples
JTree tree = new JTree() {
@Override public void updateUI() {
super.updateUI();
setEditable(true);
setCellEditor(makeTreeCellEditor(this));
}
@Override public boolean isPathEditable(TreePath path) {
appendLog("JTree#isPathEditable(TreePath)");
return Optional.ofNullable(path.getLastPathComponent())
.filter(TreeNode.class::isInstance)
.map(node -> {
boolean isLeaf = ((TreeNode) node).isLeaf();
appendLog(String.format(" isLeaf: %s", isLeaf));
if (node instanceof DefaultMutableTreeNode) {
int lv = ((DefaultMutableTreeNode) node).getLevel();
appendLog(String.format(" getLevel: %d", lv));
}
return isLeaf;
})
.orElse(false);
}
private TreeCellEditor makeTreeCellEditor(JTree tree) {
return new DefaultTreeCellEditor(
tree, (DefaultTreeCellRenderer) tree.getCellRenderer()) {
@Override public boolean isCellEditable(EventObject e) {
appendLog("TreeCellEditor#isCellEditable(EventObject)");
boolean ret;
if (e instanceof MouseEvent) {
MouseEvent me = (MouseEvent) e;
appendLog(" MouseEvent");
appendLog(String.format(" getPoint(): %s", me.getPoint()));
appendLog(String.format(" getClickCount: %d", me.getClickCount()));
appendLog(String.format(" isShiftDown: %s", me.isShiftDown()));
appendLog(String.format(" isControlDown: %s", me.isControlDown()));
ret = me.getClickCount() >= 2 || me.isShiftDown() || me.isControlDown();
} else if (e instanceof KeyEvent) {
appendLog(" KeyEvent");
ret = super.isCellEditable(e);
} else { // e == null
appendLog(" startEditing Action(F2)");
ret = super.isCellEditable(e);
}
return ret;
}
};
}
};
View in GitHub: Java, KotlinDescription
JTree#isPathEditable(TreePath)- JTree#isPathEditable(TreePath) (Java Platform SE 8)
- デフォルトの
JTreeでは引数のTreePathは参照せずに常にJTree#isEditable()を返すだけの関数のため、この関数は通常オーバーライドして使用する - このサンプルではこの関数をオーバーライドして葉ノードの場合のみ編集可能と設定
- 後述の
TreeCellEditor#isCellEditable(EventObject)より先に実行される - 引数の
TreePathからパス内の要素数(TreePath#getPathCount())や親TreePathなどを取得して編集可・不可を判断できる - 引数の
TreePathからTreePath#getLastPathComponent()でこのパスの最後の要素(TreeNode、DefaultMutableTreeNode)を取得できるので、葉ノードかどうか(TreeNode#isLeaf())やユーザーオブジェクト(DefaultMutableTreeNode#getUserObject())の状態を調査して編集可・不可を判断できる
TreeCellEditor#isCellEditable(EventObject)- CellEditor#isCellEditable(EventObject) (Java Platform SE 8)
- 引数の
EventObjectを使用して編集を開始できるかどうかをエディタに問い合せる - このサンプルではこの関数をオーバーライドしてダブルクリック、またはShiftキーもしくはCtrlキーがクリック時に押下されている場合編集可と設定
TableCellEditor#isCellEditable(EventObject)の場合引数のEventObjectがKeyEventになる場合があるがDefaultTreeCellEditor#isCellEditable(EventObject)の場合はMouseEventかnullのみになる?startEditingアクション(F2)の場合引数のEventObjectはnull
- 引数の
EventObjectがMouseEventの場合JTree#isPathEditable(TreePath)のTreePathでは取得できない以下のような情報で編集可・不可を判断できるMouseEvent#getPoint()でJTree座標系のクリックされた位置MouseEvent#getClickCount()でクリック数MouseEvent#isShiftDown()、MouseEvent#isControlDown()などでクリックと同時にShiftキーなどが押されているか
MouseEvent#getComponent()で親JTreeを参照しJTree#getPathForLocation(x, y)でTreePath、JTree#getLastSelectedPathComponent()でTreeNodeを取得する方法もあるが、それだけの場合はJTree#isPathEditable(TreePath)を使用すべき?- たとえばJCheckBoxをグループでまとめて有効化するのように編集対象ノードのユーザーオブジェクトの状態で編集可・不可を判断する場合、
JTree#isPathEditable(TreePath)よりあとに実行されるTreeCellEditor#isCellEditable(EventObject)で調査するとユーザーオブジェクトが編集不可なのに一瞬デフォルトの?(または直前に使用された?)編集可TreeCellEditorが表示されてしまう
- たとえばJCheckBoxをグループでまとめて有効化するのように編集対象ノードのユーザーオブジェクトの状態で編集可・不可を判断する場合、
Reference
- JTree#isPathEditable(TreePath) (Java Platform SE 8)
- CellEditor#isCellEditable(EventObject) (Java Platform SE 8)
- JCheckBoxをグループでまとめて有効化する
JTree#isPathEditable(TreePath)をオーバーライドしてTreePathからDefaultMutableTreeNode、ユーザーオブジェクトを順に取得し、これが編集可状態の場合のみノードエディタを起動
- JTreeのノード編集をJPopupMenuからのみに制限する
TreeCellEditor#isCellEditable(EventObject)をオーバーライドしてEventObjectがMouseEventではない場合のみノードエディタを起動
- JTreeのノードにクリック可能なJButtonを複数配置する
TreeCellEditor#isCellEditable(EventObject)をオーバーライドしてEventObjectがMouseEvent、かつクリック位置がセルレンダラー内に配置されたボタン上の場合のみノードエディタを起動