TITLE:JComboBoxのItemをTree状に表示する
#navi(../)
RIGHT:Posted by &author(aterai); at 2011-07-11
*JComboBoxのItemをTree状に表示する [#mfee4e22]
JComboBoxのドロップダウンリストに表示するItemをTree状に配置します。

-&jnlp;
-&jar;
-&zip;

//#screenshot
#ref(https://lh6.googleusercontent.com/-5GlQEjeLoH8/ThqUIL9b4UI/AAAAAAAAA_E/9h5dxYzSSm8/s800/TreeComboBox.png)

**サンプルコード [#r862e8e5]
#code(link){{
class TreeComboBox extends JComboBox {
  public TreeComboBox() {
    super();
    setRenderer(new DefaultListCellRenderer() {
      @Override public Component getListCellRendererComponent(
          JList list, Object value, int index,
          boolean isSelected, boolean cellHasFocus) {
        JComponent c;
        if(value instanceof DefaultMutableTreeNode) {
          DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
          int indent = 2 + (index<0?0:(node.getPath().length-2)*16);
          if(node.isLeaf()) {
            c = (JComponent)super.getListCellRendererComponent(
                list,value,index,isSelected,cellHasFocus);
          }else{
            c = (JComponent)super.getListCellRendererComponent(
                list,value,index,false,false);
            JLabel l = (JLabel)c;
            l.setForeground(Color.WHITE);
            l.setBackground(Color.GRAY.darker());
          }
          c.setBorder(BorderFactory.createEmptyBorder(0,indent,0,0));
        }else{
          c = (JComponent)super.getListCellRendererComponent(
              list,value,index,isSelected,cellHasFocus);
        }
        return c;
      }
    });
    Action up = new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        int si = getSelectedIndex();
        for(int i = si-1;i>=0;i--) {
          Object o = getItemAt(i);
          if(o instanceof TreeNode && ((TreeNode)o).isLeaf()) {
            setSelectedIndex(i);
            break;
          }
        }
      }
    };
    Action down = new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        int si = getSelectedIndex();
        for(int i = si+1;i<getModel().getSize();i++) {
          Object o = getItemAt(i);
          if(o instanceof TreeNode && ((TreeNode)o).isLeaf()) {
            setSelectedIndex(i);
            break;
          }
        }
      }
    };
    ActionMap am = getActionMap();
    am.put("selectPrevious3", up);
    am.put("selectNext3", down);
    InputMap im = getInputMap();
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0),      "selectPrevious3");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_KP_UP, 0),   "selectPrevious3");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0),    "selectNext3");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_KP_DOWN, 0), "selectNext3");
  }
  private boolean isNotSelectableIndex = false;
  @Override public void setPopupVisible(boolean v) {
    if(!v && isNotSelectableIndex) {
      isNotSelectableIndex = false;
    }else{
      super.setPopupVisible(v);
    }
  }
  @Override public void setSelectedIndex(int index) {
    Object o = getItemAt(index);
    if(o instanceof TreeNode && !((TreeNode)o).isLeaf()) {
      isNotSelectableIndex = true;
    }else{
      super.setSelectedIndex(index);
    }
  }
}
}}

**解説 [#k6b519eb]
上記のサンプルでは、TreeModelから取得したTreeNodeをJComboBoxのItemとして、ドロップダウンリストに表示しています。

- TreeNode#isLeaf()の場合だけ、選択可能
-- [[JComboBoxのアイテムを選択不可にする>Swing/DisableItemComboBox]]
- 子要素のインデントはBorderFactory.createEmptyBorder(0,indent,0,0)

**参考リンク [#hfd4fbb7]
- [http://www.jroller.com/santhosh/entry/tree_inside_jcombobox Tree inside JComboBox - Santhosh Kumar's Weblog]
-- こちらで解説されているサンプルでは、TreeCellRendererを使っているのでノードアイコンなどもJTreeのものを表示できるようになっています。
- [[JComboBoxのアイテムを選択不可にする>Swing/DisableItemComboBox]]

**コメント [#k2ac0bc1]
- src.zipなどが正しいディレクトリに配置されてなかったのを修正。 -- [[aterai]] &new{2011-07-13 (水) 19:02:23};

#comment