JTreeは、TreeCellRendererとTreeCellEditorを使用して、次の3つのカスタムノードを表示します。
- 単一のJCheckBox
- 単一のJButton
- 任意のアクションコンポーネントで構成されるJPanel(ここでは北のJCheckBoxと南のJButtonです)
スクリーンショット:http://i.imgur.com/9j6B2ji.png
Java Runtime Environment 6を使用する場合、このようなツリーに問題はありません。
Java Runtime Environment 7を使用する以外に、JPanelノード内のJButtonをクリックすると問題が発生します。JButtonの「クリック」アニメーションは、JPanelを最初にクリックしたとき(およびJPanelのあるノードの編集が停止した後)にはレンダリングされません。最初のノードJCheckBoxと2番目のノードJButtonは、jre6とjre7のどちらでも完全に機能しています。
以前のjre6とまったく同じように機能させたいのですが、回避策はありますか?
注:ボタンにコードを実行させることは問題ではありません。
import java.awt.BorderLayout;
import java.awt.Component;
import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreeCellRenderer;
class TreeNodeModel{
public boolean isJCheckBox = false;
public boolean isJButton = false;
public boolean isJPanel = false;
public Component userObject = null;
public TreeNodeModel(String name){
if( name.equals("JCheckBox") ){
isJCheckBox = true;
}else if( name.equals("JButton") ){
isJButton = true;
}else if( name.equals("JPanel") ){
isJPanel = true;
}
}
}
class CustomTreeCellRenderer implements TreeCellRenderer{
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
Component returnValue = null;
if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
if (userObject instanceof TreeNodeModel) {
TreeNodeModel node = (TreeNodeModel) userObject;
if(node.isJButton){
returnValue = new JButton("Ok");
}else if(node.isJCheckBox){
returnValue = new JCheckBox("Ok");
}else{
JPanel panel = new JPanel(new BorderLayout());
panel.add(new JButton("Problem"), BorderLayout.SOUTH);
panel.add(new JCheckBox("Problem"), BorderLayout.NORTH);
returnValue = panel;
}
}
}
if(returnValue == null)
returnValue = new DefaultTreeCellRenderer().getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
return returnValue;
}
}
class CustomTreeCellEditor extends AbstractCellEditor implements TreeCellEditor {
public Component getTreeCellEditorComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row) {
Component returnValue = null;
if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
if (userObject instanceof TreeNodeModel) {
TreeNodeModel node = (TreeNodeModel) userObject;
if(node.isJButton){
returnValue = new JButton("Ok");
}else if(node.isJCheckBox){
returnValue = new JCheckBox("Ok");
}else{
JPanel panel = new JPanel(new BorderLayout());
panel.add(new JButton("Problem"), BorderLayout.SOUTH);
panel.add(new JCheckBox("Problem"), BorderLayout.NORTH);
returnValue = panel;
}
}
}
return returnValue;
}
@Override
public Object getCellEditorValue() { return null; }
}
public class MyTestRendererEditor extends JFrame {
public MyTestRendererEditor() {
DefaultMutableTreeNode node = new DefaultMutableTreeNode("root");
node.add(new DefaultMutableTreeNode(new TreeNodeModel("JCheckBox")));
node.add(new DefaultMutableTreeNode(new TreeNodeModel("JButton")));
node.add(new DefaultMutableTreeNode(new TreeNodeModel("JPanel")));
final JTree tree = new JTree(new DefaultTreeModel(node));
tree.setCellRenderer(new CustomTreeCellRenderer());
tree.setCellEditor(new CustomTreeCellEditor());
tree.setEditable(true);
getContentPane().add(new JScrollPane(tree));
pack();
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new MyTestRendererEditor();
}
});
}
}