Summary

JListのセルにJCheckBoxを追加し、これをマウスでクリックするとセルの選択・解除が可能になるよう設定します。

Source Code Examples

private void cellPressed(MouseEvent e, int index) {
  if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() > 1) {
    ListItem item = getModel().getElementAt(index);
    JOptionPane.showMessageDialog(getRootPane(), item.getTitle());
  } else {
    checkedIndex = -1;
    getCheckBoxAt(e, index).ifPresent(button -> {
      checkedIndex = index;
      if (isSelectedIndex(index)) {
        removeSelectionInterval(index, index);
      } else {
        setSelectionInterval(index, index);
      }
    });
  }
}

private Optional<Component> getCheckBoxAt(MouseEvent e, int index) {
  JList<E> list = RubberBandSelectionList.this;
  boolean b = e.isShiftDown() || e.isControlDown() || e.isAltDown();
  return b ? Optional.empty() : getDeepestBoxAt(list, index, e.getPoint());
}

private Optional<Component> getDeepestBoxAt(JList<E> list, int index, Point pt) {
  E proto = list.getPrototypeCellValue();
  ListCellRenderer<? super E> cr = list.getCellRenderer();
  Component c = cr.getListCellRendererComponent(list, proto, index, false, false);
  Rectangle r = list.getCellBounds(index, index);
  c.setBounds(r);
  pt.translate(-r.x, -r.y);
  return Optional.ofNullable(SwingUtilities.getDeepestComponentAt(c, pt.x, pt.y))
      .filter(b -> b instanceof JCheckBox || b instanceof Box.Filler);
}
View in GitHub: Java, Kotlin

Description

  • 左: デフォルトのJListで複数選択する場合はCtrl+クリックのようにキーボードとマウス操作を組み合わせて使用する必要がある
  • 右: セル選択とセル選択解除を実行する機能はJListのセルに項目選択チェックボックスを追加するで使用したMouseListenerとほぼ同じ
    • 範囲選択機能などは除去している
    • セルがクリックされたときその位置に存在するコンポーネントを検索する方法も同様にSwingUtilities.getDeepestComponentAt(...)メソッドを使用しているが、こちらのサンプルではJCheckBoxを非表示にする場合は代わりにBox.Fillerを追加してセルとラベルの間隔を維持するセルレンダラーを作成しているため、クリック位置の最深部のコンポーネントがBox.Fillerの場合もJCheckBoxがクリックされたと判断している

Reference

Comment