---
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
---
* 概要 [#summary]
`JLabel`を継承するヘッダの`TableCellRenderer`に`HTML`フォーマットの`input`タグで生成した`checkbox`を表示し、クリックに応じてその状態を変更します。

#download(https://lh3.googleusercontent.com/-vnWIjLh4mRA/VtMSSVOc3gI/AAAAAAAAOPo/41aAmP3gMuc/s800-Ic42/InputTypeCheckBox.png)

* サンプルコード [#sourcecode]
#code(link){{
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();
    Component c = r.getTableCellRendererComponent(
        table, INPUT, isSelected, hasFocus, row, column);
    if (c instanceof JLabel) {
      for (Component cmp : ((JLabel) c).getComponents()) {
        updateCheckBox(((Container) cmp).getComponent(0), value);
      }
    }
    return c;
  }

  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");
        }
      }
    }
  }
}
}}

* 解説 [#explanation]
- `NimbusLookAndFeel`で[[JTableHeaderにJCheckBoxを追加してセルの値を切り替える>Swing/TableHeaderCheckBox]]のように`JCheckBox`をアイコン化してこれをヘッダセルレンダラーに`JLabel#setIcon(...)`を使用して設定すると、ソートアイコンの設定と干渉(ソートを使用しない場合でも)して意図した表示にならない場合がある
- そのためサンプルでは、アイコン化した`JCheckBox`ではなく`HTML`フォーマットの`<input type='checkbox'>`タグを`JLabel#setText(...)`メソッドで設定してチェックボックスを表示
- `<input>`要素の`checked`属性を使用して選択状態の`JCheckBox`を表示可能だが、`disabled`属性で無効状態にできない
- 代わりに`HTML`コンポーネントのレンダリングを行うコンポーネントを`JLabel`から取得し、その子要素から`JCheckBox`自体を取得して直接`JCheckBox#setEnabled(...)`、`JCheckBox#setSelected(...)`メソッドで状態を変更
-- [https://stackoverflow.com/questions/7958378/listening-to-html-check-boxes-in-jtextpane-or-an-alternative java - Listening to HTML check boxes in jTextPane (or an alternative)? - Stack Overflow]
- `Java 8`以外の`Java 17`など?で実行するとヘッダのチェックボックス描画が更新されない場合がある?
- `Java 11`以降で実行するとヘッダのチェックボックス描画が更新されない場合がある?
-- 調査中
-- `Java 8`では問題なし

* 参考リンク [#reference]
- [https://stackoverflow.com/questions/7958378/listening-to-html-check-boxes-in-jtextpane-or-an-alternative java - Listening to HTML check boxes in jTextPane (or an alternative)? - Stack Overflow]
- [[JTableHeaderにJCheckBoxを追加してセルの値を切り替える>Swing/TableHeaderCheckBox]]

* コメント [#comment]
#comment
#comment