• category: swing folder: InputTypeCheckBox title: JLabelにHTMLフォーマットのinputタグで生成したcheckboxを表示する tags: [JLabel, HTML, JTableHeader, JCheckBox, NimbusLookAndFeel] author: aterai pubdate: 2016-02-29T00:30:08+09:00 description: JLabelを継承するヘッダのTableCellRendererにHTMLフォーマットのinputタグで生成したcheckboxを表示し、クリックに応じてその状態を変更します。 image: https://lh3.googleusercontent.com/-vnWIjLh4mRA/VtMSSVOc3gI/AAAAAAAAOPo/41aAmP3gMuc/s800-Ic42/InputTypeCheckBox.png

概要

JLabelを継承するヘッダのTableCellRendererHTMLフォーマットのinputタグで生成したcheckboxを表示し、クリックに応じてその状態を変更します。

サンプルコード

class HeaderRenderer implements TableCellRenderer {
  private static String INPUT = "<html><table cellpadding='0' cellspacing='0'>"
                              + "<td><input type='checkbox'><td>&nbsp;Check All";
  @Override public Component getTableCellRendererComponent(
      JTable table, Object value, boolean isSelected, boolean hasFocus,
      int row, int column) {
    TableCellRenderer r = table.getTableHeader().getDefaultRenderer();
    JLabel l = (JLabel) r.getTableCellRendererComponent(
        table, INPUT, isSelected, hasFocus, row, column);
    for (Component c : l.getComponents()) {
      updateCheckBox(((Container) c).getComponent(0), value);
    }
    return l;
  }
  private static void updateCheckBox(Component c, Object value) {
    if (c instanceof JCheckBox) {
      JCheckBox check = (JCheckBox) c;
      check.setOpaque(false);
      check.setBorder(BorderFactory.createEmptyBorder());
      //check.setText("Check All");
      if (value instanceof Status) {
        switch ((Status) value) {
        case SELECTED:
          check.setSelected(true);
          check.setEnabled(true);
          break;
        case DESELECTED:
          check.setSelected(false);
          check.setEnabled(true);
          break;
        case INDETERMINATE:
          check.setSelected(true);
          check.setEnabled(false);
          break;
        default:
          throw new AssertionError("Unknown Status");
        }
      }
    }
  }
}
View in GitHub: Java, Kotlin

解説

NimbusLookAndFeelJTableHeaderにJCheckBoxを追加してセルの値を切り替えるのようにJCheckBoxをアイコン化し、これをヘッダセルレンダラーにJLabel#setIcon(...)を使用して設定すると、ソートアイコンの設定と干渉(ソートを使用しない場合でも)して意図した表示にならない場合があります。このサンプルでは、HTMLフォーマットの<input type='checkbox' />タグをJLabel#setText(...)を使用して設定することでチェックボックスを表示しています。

  • <input>要素のchecked属性を使用して選択状態のJCheckBoxを表示可能だが、disabled属性で無効状態にできない
  • 代わりに、HTMLコンポーネントのレンダリングを行うコンポーネントをJLabelから取得し、その子要素からJCheckBox自体を取得して、直接JCheckBox#setEnabled(...)JCheckBox#setSelected(...)で状態を変更

参考リンク

コメント