Swing/CheckBoxNodeEditor のバックアップ差分(No.1)
- バックアップ一覧
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- バックアップ を表示
- Swing/CheckBoxNodeEditor へ行く。
- 1 (2012-02-06 (月) 14:38:59)
- 2 (2012-02-07 (火) 13:58:43)
- 3 (2012-03-23 (金) 17:43:32)
- 4 (2012-05-10 (木) 10:52:04)
- 5 (2012-05-11 (金) 16:50:47)
- 6 (2012-12-13 (木) 15:41:34)
- 7 (2013-08-17 (土) 15:37:51)
- 8 (2014-02-18 (火) 15:23:02)
- 9 (2014-03-04 (火) 02:49:03)
- 10 (2014-03-04 (火) 11:06:52)
- 11 (2014-07-04 (金) 15:12:37)
- 12 (2014-08-15 (金) 19:46:41)
- 13 (2014-09-17 (水) 13:10:51)
- 14 (2014-10-22 (水) 00:52:41)
- 15 (2014-11-26 (水) 02:34:41)
- 16 (2015-02-06 (金) 11:59:40)
- 17 (2015-04-02 (木) 15:09:47)
- 18 (2017-02-22 (水) 13:58:44)
- 19 (2017-11-02 (木) 15:34:40)
- 20 (2017-12-28 (木) 22:28:33)
- 21 (2018-02-24 (土) 19:51:30)
- 22 (2019-05-22 (水) 19:35:38)
- 23 (2019-12-18 (水) 19:52:49)
- 24 (2021-06-19 (土) 17:20:17)
- 25 (2022-08-20 (土) 22:15:25)
- 追加された行はこの色です。
- 削除された行はこの色です。
TITLE:JTreeのすべてのノードにJCheckBoxを追加する #navi(../) RIGHT:Posted by [[aterai]] at 2012-02-06 *JTreeのすべてのノードにJCheckBoxを追加する [#v2eb0f91] JTreeのすべてのノードに編集可能なJCheckBoxを追加します。 -&jnlp; -&jar; -&zip; //#screenshot #ref(https://lh4.googleusercontent.com/-DK6aW3VNikg/TygxL3j8UoI/AAAAAAAABIw/6_9FyPe4v7U/s800/CheckBoxNodeEditor.png) **サンプルコード [#pdf0395c] #code{{ class CheckBoxNodeEditor extends TriStateCheckBox implements TreeCellEditor { private DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer(); private final JPanel panel = new JPanel(new BorderLayout()); private String str = null; public CheckBoxNodeEditor() { super(); this.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { //System.out.println("actionPerformed: stopCellEditing"); stopCellEditing(); } }); panel.setFocusable(false); panel.setRequestFocusEnabled(false); panel.setOpaque(false); panel.add(this, BorderLayout.WEST); this.setOpaque(false); } @Override public Component getTreeCellEditorComponent( JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) { JLabel l = (JLabel)renderer.getTreeCellRendererComponent( tree, value, true, expanded, leaf, row, true); l.setFont(tree.getFont()); if(value != null && value instanceof DefaultMutableTreeNode) { this.setEnabled(tree.isEnabled()); this.setFont(tree.getFont()); Object userObject = ((DefaultMutableTreeNode)value).getUserObject(); if(userObject!=null && userObject instanceof CheckBoxNode) { CheckBoxNode node = (CheckBoxNode)userObject; if(!node.selected && node.indeterminate) { setIcon(new IndeterminateIcon()); } else { setIcon(null); } l.setText(node.str); setSelected(node.selected); str = node.str; } //panel.add(this, BorderLayout.WEST); panel.add(l); return panel; } return l; } @Override public Object getCellEditorValue() { return new CheckBoxNode(str, isSelected()); } @Override public boolean isCellEditable(EventObject e) { if(e != null && e instanceof MouseEvent && e.getSource() instanceof JTree) { MouseEvent me = (MouseEvent)e; JTree tree = (JTree)e.getSource(); TreePath path = tree.getPathForLocation(me.getX(), me.getY()); Rectangle r = tree.getPathBounds(path); if(r==null) return false; Dimension d = getPreferredSize(); r.setSize(new Dimension(d.width, r.height)); if(r.contains(me.getX(), me.getY())) { if(str==null && System.getProperty("java.version").startsWith("1.7.0")) { System.out.println("XXX: Java 7, only on first run\n"+getBounds()); setBounds(new Rectangle(0,0,d.width,r.height)); } //System.out.println(getBounds()); return true; } } return false; } @Override public void updateUI() { super.updateUI(); setName("Tree.cellEditor"); if(panel!=null) { //panel.removeAll(); //??? Change to Nimbus LnF, JDK 1.6.0 panel.updateUI(); //panel.add(this, BorderLayout.WEST); } //???#1: JDK 1.6.0 bug??? @see 1.7.0 DefaultTreeCellRenderer#updateUI() //if(System.getProperty("java.version").startsWith("1.6.0")) { // renderer = new DefaultTreeCellRenderer(); //} } //... }} **解説 [#a6fcfbcf] 上記のサンプルでは、JCheckBoxを継承する TreeCellEditor、TreeCellRenderer を作成し、TreeCellEditor#getTreeCellEditorComponent(...)などは、このJCheckBox、JLabel(文字列、アイコン)などを含むJPanel を生成して返しています。 JPanelを継承する TreeCellEditor、TreeCellRenderer でも、JDK 1.7.0, 1.6.0_30 などでは、問題なく動作するようです。 #code{{ class CheckBoxNodeRenderer extends TriStateCheckBox implements TreeCellRenderer { private DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer(); private final JPanel panel = new JPanel(new BorderLayout()); private JTree tree = null; public CheckBoxNodeRenderer() { super(); String uiName = getUI().getClass().getName(); if(uiName.contains("Synth") && System.getProperty("java.version").startsWith("1.7.0")) { System.out.println("XXX: FocusBorder bug?, JDK 1.7.0, Nimbus start LnF"); renderer.setBackgroundSelectionColor(new Color(0,0,0,0)); } panel.setFocusable(false); panel.setRequestFocusEnabled(false); panel.setOpaque(false); panel.add(this, BorderLayout.WEST); this.setOpaque(false); } @Override public Component getTreeCellRendererComponent( JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { this.tree = tree; JLabel l = (JLabel)renderer.getTreeCellRendererComponent( tree, value, selected, expanded, leaf, row, hasFocus); l.setFont(tree.getFont()); if(value != null && value instanceof DefaultMutableTreeNode) { this.setEnabled(tree.isEnabled()); this.setFont(tree.getFont()); Object userObject = ((DefaultMutableTreeNode)value).getUserObject(); if(userObject!=null && userObject instanceof CheckBoxNode) { CheckBoxNode node = (CheckBoxNode)userObject; if(!node.selected && node.indeterminate) { setIcon(new IndeterminateIcon()); } else { setIcon(null); } l.setText(node.str); setSelected(node.selected); } //panel.add(this, BorderLayout.WEST); panel.add(l); return panel; } return l; } @Override public void updateUI() { super.updateUI(); if(panel!=null) { //panel.removeAll(); //??? Change to Nimbus LnF, JDK 1.6.0 panel.updateUI(); //panel.add(this, BorderLayout.WEST); } setName("Tree.cellRenderer"); //???#1: JDK 1.6.0 bug??? @see 1.7.0 DefaultTreeCellRenderer#updateUI() //if(System.getProperty("java.version").startsWith("1.6.0")) { // renderer = new DefaultTreeCellRenderer(); //} } } }} ---- ノードのチェック変更で、子ノードのチェックをすべて揃えたり、親ノードの状態変更は、TreeModelListenerを追加して行なっています。 ---- - JDK 1.6.0 で、Look&Feel を Nimbus などに変更すると、セルエディタなどが更新されず?表示がおかしくなる場合があるので、JTree#updateUI()を以下のようにオーバーライドして回避。 #code{{ JTree tree = new JTree() { @Override public void updateUI() { setCellRenderer(null); setCellEditor(null); super.updateUI(); //???#1: JDK 1.6.0 bug??? Nimbus LnF setCellRenderer(new CheckBoxNodeRenderer()); setCellEditor(new CheckBoxNodeEditor()); } }; }} - JDK 1.7.0 で、初期Look&Feel を Nimbus にすると、ノードにフォーカスがある場合のグラデーション描画がノードの背景色で塗りつぶされてしまう?のを、以下のようにして回避。 #code{{ public CheckBoxNodeRenderer() { super(); String uiName = getUI().getClass().getName(); if(uiName.contains("Synth") && System.getProperty("java.version").startsWith("1.7.0")) { System.out.println("XXX: FocusBorder bug?, JDK 1.7.0, Nimbus start LnF"); renderer.setBackgroundSelectionColor(new Color(0,0,0,0)); } }} - JDK 1.7.0 で、ノードのチェックボックスをクリックしても、初回だけ反応しない。 -- JDK 1.6.0_30 などは問題なし -- TreeCellEditor#isCellEditable()をオーバーライドして、初回のみセルエディタのサイズを以下のように設定。 #code{{ if(isFirstTime && System.getProperty("java.version").startsWith("1.7.0")) { System.out.println("XXX: Java 7, only on first run\n"+getBounds()); setBounds(new Rectangle(0,0,d.width,r.height)); } }} **参考リンク [#ab7883bf] - [[JTreeの葉ノードをJCheckBoxにする>Swing/CheckBoxNodeTree]] **コメント [#nbcaf27c] #comment