概要

JCheckBoxを同じJPanelJComboBoxのリスト配置されているかでグループ化し、そのグループ内で選択可能なJCheckBoxの数を制限します。

サンプルコード

class GroupCheckBox extends JCheckBox {
  protected GroupCheckBox(String title) {
    super(title);
  }

  @Override public void updateUI() {
    super.updateUI();
    setModel(new ToggleButtonModel() {
      private static final int GROUP_SIZE = 3;

      @Override public void setSelected(boolean selected) {
        if (selected) {
          if (getSelectedObjects().length == GROUP_SIZE) {
            UIManager.getLookAndFeel()
                .provideErrorFeedback(GroupCheckBox.this);
          } else {
            super.setSelected(true);
          }
        } else {
          super.setSelected(false);
        }
      }

      @Override public Object[] getSelectedObjects() {
        Container parent = getParent();
        return Arrays.stream(parent.getComponents())
            .filter(AbstractButton.class::isInstance)
            .map(AbstractButton.class::cast)
            .filter(AbstractButton::isSelected)
            .toArray();
      }
    });
  }
}
View in GitHub: Java, Kotlin

解説

  • JPanelでグループ化して選択可能なJCheckBoxの数を3に制限
    • ToggleButtonModel#getSelectedObjects()をオーバーライドして、親が同じJPanelに配置された選択状態のJCheckBoxの配列を取得
    • ToggleButtonModel#setSelected(boolean)をオーバーライドして、選択状態のJCheckBoxの数が3の場合はsuper.setSelected(true)を実行せずに選択を取り消す
    • ビューであるJCheckBoxgetSelectedObjects()setSelected(boolean)をオーバーライドしても選択の取り消しなどが実行不可なので、モデル側のToggleButtonModelgetSelectedObjects()setSelected(boolean)をオーバーライドし、JCheckBox#setModel(...)で設定している
  • JComboBoxのドロップダウンリストでグループ化して選択可能なJCheckBoxの数を3に制限
    • JComboBoxのアイテムとして表示したJCheckBoxを複数選択するのようにドロップダウンリストにJCheckBoxを表示して複数選択可能に設定
    • ドロップダウンリストに表示するJCheckBoxは表示用のListCellRendererとして使い回しているため、上記のGroupCheckBoxを使用しても効果がない
    • JComboBox#getSelectedObjects()をオーバーライドして、選択状態のリストアイテム配列を取得
    • ドロップダウンリストにMouseListenerを追加し、クリック時にJComboBox#getSelectedObjects()で選択状態のリストアイテムを取得し、その数がすでに3の場合はリストアイテムの選択を取り消す

参考リンク

コメント