Swing/CheckBoxNodeTree のバックアップの現在との差分(No.2)
TITLE:JTreeの葉ノードをJCheckBoxにする
Posted by aterai at 2011-03-21
JTreeの葉ノードをJCheckBoxにする
JTreeの葉ノードを編集可能なJCheckBoxにします。- category: swing folder: CheckBoxNodeTree title: JTreeの葉ノードをJCheckBoxにする tags: [JTree, JCheckBox, TreeCellRenderer, TreeCellEditor] author: aterai pubdate: 2011-03-21T16:05:37+09:00 description: JTreeの葉ノードを編集可能なJCheckBoxにします。 image:
概要
JTree
の葉ノードを編集可能なJCheckBox
にします。
- &jnlp;
- &jar;
- &zip;
Screenshot
Advertisement
サンプルコード
#spanend
#spanadd
* サンプルコード [#sourcecode]
#spanend
#spanadd
#code(link){{
#spanend
class CheckBoxNode {
public final String text;
public final boolean selected;
public CheckBoxNode(String text, boolean selected) {
this.text = text;
this.selected = selected;
}
#spanadd
#spanend
@Override public String toString() {
return text;
}
}
#spandel
#spanend
#spanadd
#spanend
#spanadd
JTree tree = new JTree() {
#spanend
@Override public void updateUI() {
setCellRenderer(null);
setCellEditor(null);
super.updateUI();
// ???: JDK 1.6.0 LnF bug???
setCellRenderer(new CheckBoxNodeRenderer());
setCellEditor(new CheckBoxNodeEditor());
}
#spanadd
};
#spanend
#spanadd
#spanend
class CheckBoxNodeRenderer extends JCheckBox implements TreeCellRenderer {
private JTree tree = null;
private DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
@Override public Component getTreeCellRendererComponent(JTree tree,
Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
Object value, boolean selected, boolean expanded,
boolean leaf, int row, boolean hasFocus) {
this.tree = tree;
if(leaf && value != null && value instanceof DefaultMutableTreeNode) {
if (leaf && value instanceof DefaultMutableTreeNode) {
this.setEnabled(tree.isEnabled());
this.setFont(tree.getFont());
this.setOpaque(false);
Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
if(userObject!=null && userObject instanceof CheckBoxNode) {
CheckBoxNode node = (CheckBoxNode)userObject;
Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
if (userObject instanceof CheckBoxNode) {
CheckBoxNode node = (CheckBoxNode) userObject;
this.setText(node.text);
this.setSelected(node.selected);
}
return this;
}
return renderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
return renderer.getTreeCellRendererComponent(
tree, value, selected, expanded, leaf, row, hasFocus);
}
private JTree tree = null;
private DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
#spanadd
#spanend
@Override public void updateUI() {
super.updateUI();
setName("Tree.cellRenderer");
//1.6.0_24 bug??? @see 1.7.0 DefaultTreeCellRenderer#updateUI()
renderer = new DefaultTreeCellRenderer();
if(tree!=null) { //update all node width???
DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode)model.getRoot();
java.util.Enumeration depth = root.depthFirstEnumeration();
while(depth.hasMoreElements()) {
model.nodeChanged((TreeNode)depth.nextElement());
}
}
}
}
#spandel
#spanend
#spanadd
#spanend
class CheckBoxNodeEditor extends JCheckBox implements TreeCellEditor {
private final JTree tree;
public CheckBoxNodeEditor(JTree tree) {
super();
this.tree = tree;
setFocusable(false);
setRequestFocusEnabled(false);
setOpaque(false);
addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
stopCellEditing();
}
});
}
#spanadd
#spanend
@Override public Component getTreeCellEditorComponent(JTree tree,
Object value, boolean isSelected, boolean expanded, boolean leaf, int row) {
if(leaf && value != null && value instanceof DefaultMutableTreeNode) {
Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
if(userObject!=null && userObject instanceof CheckBoxNode) {
this.setSelected(((CheckBoxNode)userObject).selected);
}else{
if (leaf && value instanceof DefaultMutableTreeNode) {
Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
if (userObject instanceof CheckBoxNode) {
this.setSelected(((CheckBoxNode) userObject).selected);
} else {
this.setSelected(false);
}
this.setText(value.toString());
}
return this;
}
#spanadd
#spanend
@Override public Object getCellEditorValue() {
return new CheckBoxNode(getText(), isSelected());
}
#spanadd
#spanend
@Override public boolean isCellEditable(EventObject e) {
if(e != null && e instanceof MouseEvent) {
if (e instanceof MouseEvent) {
TreePath path = tree.getPathForLocation(
((MouseEvent)e).getX(), ((MouseEvent)e).getY());
((MouseEvent) e).getX(), ((MouseEvent) e).getY());
Object o = path.getLastPathComponent();
if(o!=null && o instanceof TreeNode) {
return ((TreeNode)o).isLeaf();
if (o instanceof TreeNode) {
return ((TreeNode) o).isLeaf();
}
}
return false;
}
#spandel
//......
#spanend
#spanadd
// ...
#spanend
解説
上記のサンプルでは、JCheckBox
を継承するTreeCellRenderer
とTreeCellEditor
を作成して編集可setEditable(true)
としたJTree
に設定し、葉ノードをチェックできるように設定しています。ノードがチェックされているかどうかといった状態の保存は、ノードのタイトル文字列と選択状態を保持する不変オブジェクトをDefaultMutableTreeNode#setUserObject(Object)
メソッドで設定することで実行しています。
解説
JCheckBoxを継承するTreeCellRenderer、TreeCellEditorを作成して、setEditable(true)としたJTreeに設定し、葉ノードをチェックできるようにしています。ノードがチェックされているかどうかといった状態の保存は、DefaultMutableTreeNode#setUserObject(Object)でタイトルと選択状態をもつオブジェクトを設定することで行っています。- 葉ノードだけ編集可能に制限するため、
TreeCellEditor#isCellEditable(EventObject)
でクリックしたノードがTreeNode#isLeaf()
かどうかを判断 - 葉以外のノードの描画には
DefaultTreeCellRenderer
を使用-
DefaultTreeCellRenderer
を継承するTreeCellRenderer
で、葉ノードの表示をJCheckBox
に委譲する方法でも同様-
JDK 1.6.0
ではLook And Feel
を変更してもアイコンや選択色が更新されないJDK 1.7.0
で修正済
-
-
- - 葉ノードでない場合、表示にはDefaultTreeCellRendererを使っています。逆にDefaultTreeCellRendererを継承するTreeCellRendererで、葉ノードの表示をJCheckBoxに委譲する方法でも同様となりますが、この場合、JDK 1.6.0_xx では*1 Look And Feel を変更してもアイコンや選択色が更新されないようです。
- - 葉ノードだけ編集可能に制限するため、TreeCellEditor#isCellEditable(EventObject)でクリックしたノードがTreeNode#isLeaf()かを判断しています。