TITLE:JListのセルにJCheckBoxを使用する

Posted by at 2011-03-28

JListのセルにJCheckBoxを使用する

JListのセルにJCheckBoxを使用して、チェックボックスの一覧を作成します。

  • &jnlp;
  • &jar;
  • &zip;
CheckBoxCellList.png

サンプルコード

class CheckBoxCellRenderer extends JCheckBox
    implements ListCellRenderer, MouseListener, MouseMotionListener {
  @Override public Component getListCellRendererComponent(
    JList list,
    Object value,
    int index,
    boolean isSelected,
    boolean cellHasFocus) {
    this.setOpaque(true);
    if(isSelected) {
      this.setBackground(list.getSelectionBackground());
      this.setForeground(list.getSelectionForeground());
    }else{
      this.setBackground(list.getBackground());
      this.setForeground(list.getForeground());
    }
    if(value instanceof CheckBoxNode) {
      this.setSelected(((CheckBoxNode)value).selected);
      if(index==pressedRowIndex) {
        this.getModel().setArmed(true);
        this.getModel().setPressed(true);
      }else{
        this.getModel().setRollover(index==rollOverRowIndex);
        this.getModel().setArmed(false);
        this.getModel().setPressed(false);
      }
    }
    this.setText(value.toString());
    return this;
  }
  private int rollOverRowIndex = -1;
  private int pressedRowIndex = -3;
  @Override public void mouseExited(MouseEvent e) {
    rollOverRowIndex = -1;
    JList c = (JList)e.getSource();
    c.repaint();
  }
  @Override public void mouseClicked(MouseEvent e) {
    if(e.getButton()==MouseEvent.BUTTON1) {
      JList t = (JList)e.getComponent();
      DefaultListModel m = (DefaultListModel)t.getModel();
      Point p = e.getPoint();
      int index  = t.locationToIndex(p);
      CheckBoxNode n = (CheckBoxNode)m.get(index);
      Component c = t.getCellRenderer().getListCellRendererComponent(
          t, n, index, false, false);
      Dimension d = c.getPreferredSize();
      if(d.width>=p.x) {
        m.set(index, new CheckBoxNode(n.text, !n.selected));
        t.repaint();
        t.repaint(t.getCellBounds(index, index));
      }
    }
  }
  @Override public void mouseEntered(MouseEvent e) {}
  private int pressStartIndex = -1;
  @Override public void mousePressed(MouseEvent e) {
    if(e.getButton()==MouseEvent.BUTTON1) {
      JList c = (JList)e.getSource();
      int row = c.locationToIndex(e.getPoint());
      pressStartIndex = row;
      if(row != pressedRowIndex) {
        pressedRowIndex = row;
        c.repaint();
      }
    }
  }
  @Override public void mouseReleased(MouseEvent e) {
    pressedRowIndex = -1;
    pressStartIndex = -1;
  }
  @Override public void mouseDragged(MouseEvent e) {
    JList c = (JList)e.getSource();
    int row = c.locationToIndex(e.getPoint());
    if(row != rollOverRowIndex) {
      rollOverRowIndex = -1;
    }
    if(row != pressedRowIndex) {
      pressedRowIndex = -1;
    }
    if(row == pressStartIndex) {
      pressedRowIndex = row;
    }
    c.repaint();
  }
  @Override public void mouseMoved(MouseEvent e) {
    JList c = (JList)e.getSource();
    int row = c.locationToIndex(e.getPoint());
    if(row != rollOverRowIndex) {
      rollOverRowIndex = row;
      c.repaint();
    }
  }
}

解説

  • 左: "JCheckBox Cell in JList"
    • JCheckBoxを継承するListCellRendererを設定
    • チェックボックスのロールオーバーなどは、JListにマウスリスナーを設定して表示
    • JList#putClientProperty("List.isFileList", Boolean.TRUE);で、クリックが有効になる領域をチェックボックスの幅に制限
  • 右: "JCheckBox in Box"
    • Box.createVerticalBox()にJCheckBoxを追加
    • JCheckBox#setAlignmentX(Component.LEFT_ALIGNMENT);で左揃えに設定

JTreeの葉ノードをJCheckBoxにするのセルレンダラーを使ったJTreeに、JTree#setRootVisible(false)を設定しても、ほぼ同様のチェックボックスの一覧を作成することができます。

コメント