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 final 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.getComponent();
        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);
          boolean b = column.getHeaderValue() == Status.DESELECTED;
          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;
        default:
          throw new AssertionError("Unknown Status");
        }
      } else {
        setSelected(true);
        setEnabled(false);
      }
      label.setIcon(new ComponentIcon(this));
      l.setIcon(new ComponentIcon(label));
      l.setText(null);
    }
    return l;
  }
}

class ComponentIcon implements Icon {
  private final JComponent cmp;

  public ComponentIcon(JComponent cmp) {
    this.cmp = cmp;
  }

  @Override public int getIconWidth() {
    return cmp.getPreferredSize().width;
  }

  @Override public int getIconHeight() {
    return cmp.getPreferredSize().height;
  }

  @Override public void paintIcon(Component c, Graphics g, int x, int y) {
    SwingUtilities.paintComponent(
        g, cmp, c.getParent(), x, y, getIconWidth(), getIconHeight());
  }
}

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