Swing/MultipleButtonsInTreeNode のバックアップ(No.2)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/MultipleButtonsInTreeNode へ行く。
- 1 (2018-02-13 (火) 15:56:13)
- 2 (2018-02-13 (火) 18:33:02)
- 3 (2018-02-15 (木) 14:23:42)
- 4 (2020-02-13 (木) 14:44:55)
- 5 (2021-07-31 (土) 08:07:58)
- 6 (2025-01-03 (金) 08:57:02)
- 7 (2025-01-03 (金) 09:01:23)
- 8 (2025-01-03 (金) 09:02:38)
- 9 (2025-01-03 (金) 09:03:21)
- 10 (2025-01-03 (金) 09:04:02)
- 11 (2025-06-19 (木) 12:41:37)
- 12 (2025-06-19 (木) 12:43:47)
- category: swing folder: MultipleButtonsInTreeNode title: JTreeのノードにクリック可能なJButtonを複数配置する tags: [JTree, TreeCellEditor, TreeCellRenderer, JButton, JPanel] author: aterai pubdate: 2018-02-12T19:19:08+09:00 description: JTreeのセルエディタとしてクリック可能なJButtonを複数したJPanelを設定します。 image: https://drive.google.com/uc?export=view&id=1av1tLvTqv_249jfJdwdsuhEyB5i3zikC7Q
概要
JTreeのセルエディタとしてクリック可能なJButtonを複数したJPanelを設定します。
Screenshot

Advertisement
サンプルコード
class ButtonCellEditor extends AbstractCellEditor implements TreeCellEditor {
private final ButtonPanel panel = new ButtonPanel();
protected ButtonCellEditor() {
super();
panel.b1.addActionListener(e -> {
System.out.println("b1: " + panel.renderer.getText());
stopCellEditing();
});
panel.b2.addActionListener(e -> {
System.out.println("b2: " + panel.renderer.getText());
stopCellEditing();
});
panel.b3.addActionListener(e -> {
System.out.println("b3: " + panel.renderer.getText());
stopCellEditing();
});
}
@Override public Component getTreeCellEditorComponent(
JTree tree, Object value, boolean isSelected, boolean expanded,
boolean leaf, int row) {
Component c = panel.renderer.getTreeCellRendererComponent(
tree, value, true, expanded, leaf, row, true);
return panel.remakePanel(c);
}
@Override public Object getCellEditorValue() {
return panel.renderer.getText();
}
@Override public boolean isCellEditable(EventObject e) {
Object source = e.getSource();
if (!(source instanceof JTree) || !(e instanceof MouseEvent)) {
return false;
}
JTree tree = (JTree) source;
Point p = ((MouseEvent) e).getPoint();
TreePath path = tree.getPathForLocation(p.x, p.y);
if (Objects.isNull(path)) {
return false;
}
Rectangle r = tree.getPathBounds(path);
if (Objects.isNull(r)) {
return false;
}
// r.width = panel.getButtonAreaWidth();
// return r.contains(p);
if (r.contains(p)) {
TreeNode node = (TreeNode) path.getLastPathComponent();
int row = tree.getRowForLocation(p.x, p.y);
Component c = tree.getCellRenderer().getTreeCellRendererComponent(tree, " ", true, true, node.isLeaf(), row, true);
c.setBounds(r);
c.setLocation(0, 0);
// tree.doLayout();
tree.revalidate();
p.translate(-r.x, -r.y);
Component o = SwingUtilities.getDeepestComponentAt(c, p.x, p.y);
if (o instanceof JButton) {
return true;
}
}
return false;
}
}
View in GitHub: Java, Kotlin解説
上記のサンプルでは、3つのJButtonとJLabelを継承するDefaultTreeCellRendererをFlowLayoutで配置するJPanelを2つ作成し、それぞれをJTreeのセルエディタとセルレンダラーとして設定しています。
- セルレンダラーの
JButtonは表示にのみ使用するめ、ActionListenerなどは設定しない - セルエディタの
JButtonには、JTreeのノードが編集可能になって自身がクリックされたときに実行するActionListenerを設定- この
ActionListenerが実行されたあと、AbstractCellEditor#stopCellEditing()を実行してJTreeのノード編集を終了する JTreeのノード編集を終了しないと、編集中のノードの各ボタンにフォーカスが描画されたり、別ノードのボタンを2回クリックしないとそのボタンのイベントが実行できない
- この
TreeCellEditor#isCellEditable(...)をオーバーライドし、マウスで各JButtonの表示領域がクリックされた場合のみ編集可能に設定JButtonの表示領域がクリックされたかどうかの判断は、編集開始前なのでセルエディタではなくセルレンダラー内をSwingUtilities.getDeepestComponentAt(...)で検索してJButtonが返されるかを調査している
- 編集中のノードの
JButtonのみマウスでクリック可能