Google Tag Manager

2009/02/16

JTableHeader CheckBox

Code

enum Status { SELECTED, DESELECTED, INDETERMINATE }
class HeaderRenderer extends JCheckBox implements TableCellRenderer {
  private final JLabel label = new JLabel("Check All");
  private int targetColumnIndex;
  public HeaderRenderer(JTableHeader header, int index) {
    super((String)null);
    this.targetColumnIndex = index;
    setOpaque(false);
    setFont(header.getFont());
    header.addMouseListener(new MouseAdapter() {
      @Override public void mouseClicked(MouseEvent e) {
        JTableHeader header = (JTableHeader)e.getSource();
        JTable table = header.getTable();
        TableColumnModel columnModel = table.getColumnModel();
        int vci = columnModel.getColumnIndexAtX(e.getX());
        int mci = table.convertColumnIndexToModel(vci);
        if(mci == targetColumnIndex) {
          TableColumn column = columnModel.getColumn(vci);
          Object v = column.getHeaderValue();
          boolean b = Status.DESELECTED.equals(v)?true:false;
          TableModel m = table.getModel();
          for(int i=0; i < m.getRowCount(); i++) m.setValueAt(b, i, mci);
          column.setHeaderValue(b?Status.SELECTED:Status.DESELECTED);
          //header.repaint();
        }
      }
    });
  }
  @Override public Component getTableCellRendererComponent(
      JTable tbl, Object val, boolean isS, boolean hasF, int row, int col) {
    TableCellRenderer r = tbl.getTableHeader().getDefaultRenderer();
    JLabel l =(JLabel)r.getTableCellRendererComponent(tbl,val,isS,hasF,row,col);
    if(targetColumnIndex==tbl.convertColumnIndexToModel(col)) {
      if(val instanceof Status) {
        switch((Status)val) {
          case SELECTED:    setSelected(true);  setEnabled(true);  break;
          case DESELECTED:  setSelected(false); setEnabled(true);  break;
          case INDETERMINATE: setSelected(true);  setEnabled(false); break;
        }
      }else{
        setSelected(true); setEnabled(false);
      }
      label.setIcon(new ComponentIcon(this));
      l.setIcon(new ComponentIcon(label));
      l.setText(null); //XXX: Nimbus???
    }
    return l;
  }
}
class CheckBoxIcon implements Icon{
  private final JCheckBox check;
  public CheckBoxIcon(JCheckBox check) {
    this.check = check;
  }
  @Override public int getIconWidth() {
    return check.getPreferredSize().width;
  }
  @Override public int getIconHeight() {
    return check.getPreferredSize().height;
  }
  @Override public void paintIcon(Component c, Graphics g, int x, int y) {
    SwingUtilities.paintComponent(
        g, check, (Container)c, x, y, getIconWidth(), getIconHeight());
  }
}
model.addTableModelListener(new TableModelListener() {
  @Override public void tableChanged(TableModelEvent e) {
    if(e.getType()==TableModelEvent.UPDATE && e.getColumn()==targetColumnIndex) {
      int vci = table.convertColumnIndexToView(targetColumnIndex);
      TableColumn column = table.getColumnModel().getColumn(vci);
      if(!Status.INDETERMINATE.equals(column.getHeaderValue())) {
        column.setHeaderValue(Status.INDETERMINATE);
      }else{
        boolean selected = true, deselected = true;
        TableModel m = table.getModel();
        for(int i=0; i < m.getRowCount(); i++) {
          Boolean b = (Boolean)m.getValueAt(i, targetColumnIndex);
          selected &= b; deselected &= !b;
          if(selected==deselected) return;
        }
        if(selected) {
          column.setHeaderValue(Status.SELECTED);
        }else if(deselected) {
          column.setHeaderValue(Status.DESELECTED);
        }else{
          return;
        }
      }
      JTableHeader h = table.getTableHeader();
      h.repaint(h.getHeaderRect(vci));
    }
  }
});

References

7 comments:

  1. there a problem...

    if there some checkbox who are unchecked, the header checkbox should not be checked

    ReplyDelete
  2. Hi, Marc. Thanks for the feedback.
    Possibly not what you want, but this example(JCheckBox in JTableHeader) now support the indeterminate state.

    ReplyDelete
  3. Hi, How to make this case-insensitive
    please replay me ..

    ReplyDelete
  4. Hi, waazz.
    Sorry, but I think there is no apparent connection between this example and case-insensitive.
    You've got the wrong article to comment?

    ReplyDelete