• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:JListをマウスクリックのみで複数選択する
#navi(../)
RIGHT:Posted by [[terai]] at 2011-07-18
*JListをマウスクリックのみで複数選択する [#n2f0193f]
JListをアイテムをマウスクリックだけで複数選択できるように設定します。

-&jnlp;
-&jar;
-&zip;

//#screenshot
#ref(https://lh6.googleusercontent.com/-wj2xm8BlBbA/TiPrjr1sQ5I/AAAAAAAAA_c/NiXO891B5fs/s800/ListMouseSelection.png)

**サンプルコード [#ncc6d7b3]
#code{{
JList list = new JList(model) {
  private ClearSelectionListener listener;
  @Override public void setSelectionInterval(int anchor, int lead) {
    if(anchor==lead && lead>=0 && anchor>=0) {
      if(listener.isDragging) {
        addSelectionInterval(anchor, anchor);
      }else if(!listener.isInCellDragging) {
        if(isSelectedIndex(anchor)) {
          removeSelectionInterval(anchor, anchor);
        }else{
          addSelectionInterval(anchor, anchor);
        }
        listener.isInCellDragging = true;
      }
    }else{
      super.setSelectionInterval(anchor, lead);
    }
  }
};
}}

**解説 [#cd959e47]
- 左: Default
- 中: MouseEvent
-- JList#processMouseEvent, JList#processMouseMotionEventをオーバーライドして、常にCtrlキーが押されている状態にする
-- マウスでアイテムをドラッグしても選択状態は変わらない
-- JListの空白部分をクリックした場合、アイテムの選択状態は変更せず(MouseEvent#consume())、フォーカスだけJListに移動
-- 参考: [http://forums.oracle.com/forums/thread.jspa?messageID=5692411 Thread: JList where mouse click acts like ctrl-mouse click]

#code{{
JList list = new JList(model) {
  @Override protected void processMouseMotionEvent(MouseEvent e) {
    super.processMouseMotionEvent(convertMouseEvent(e));
  }
  @Override protected void processMouseEvent(MouseEvent e) {
    if(e.getID()==MouseEvent.MOUSE_PRESSED && 
       !getCellBounds(0, getModel().getSize()-1).contains(e.getPoint())) {
      e.consume();
      requestFocusInWindow();
    }else{
      super.processMouseEvent(convertMouseEvent(e));
    }
  }
  private MouseEvent convertMouseEvent(MouseEvent e) {
    //Thread: JList where mouse click acts like ctrl-mouse click
    //http://forums.oracle.com/forums/thread.jspa?messageID=5692411
    return new MouseEvent(
      (Component) e.getSource(),
      e.getID(), e.getWhen(),
      //e.getModifiers() | InputEvent.CTRL_MASK,
      //select multiple objects in OS X: Command+click
      //pointed out by nsby
      e.getModifiers() | Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(),
      e.getX(), e.getY(),
      e.getXOnScreen(), e.getYOnScreen(),
      e.getClickCount(),
      e.isPopupTrigger(),
      e.getButton());
  }
};
}}

- 右: SelectionInterval
-- JList#setSelectionIntervalをオーバーライドして、ひとつのアイテムのセルを選択した場合は、JList#addSelectionInterval、JList#removeSelectionIntervalを使用するように変更
-- マウスでアイテムをドラッグすると、選択状態になる
-- ひとつのアイテムのセル内でのドラッグでは、選択状態を変更しない
-- 参考: [http://forums.oracle.com/forums/message.jspa?messageID=5692413#5692413 Thread: JList where mouse click acts like ctrl-mouse click]
-- JListの空白部分をクリックした場合、アイテムの選択状態をすべてクリア([[JListの選択を解除>Swing/ClearSelection]])

**参考リンク [#e59c2cca]
- [http://forums.oracle.com/forums/thread.jspa?messageID=5692411 Thread: JList where mouse click acts like ctrl-mouse click]
- [[JListの選択を解除>Swing/ClearSelection]]
- [[JListのセルにJCheckBoxを使用する>Swing/CheckBoxCellList]]

**コメント [#tdd44287]
- OSX(snow leopard)では、MouseEventは複数選択が出来ません。キーボードを使っても(command+クリック)無理でした。 -- [[nsby]] &new{2011-07-20 (水) 13:15:30};
-- ご指摘ありがとうございます。OSXでは「command+クリック」で複数選択でしたっけ? InputEvent.CTRL_MASK決め打ちではなく、Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()に修正した方がいいのかもしれません(ソースなどを更新しましたが、正常に動作するかは確認していません…)。 -- [[aterai]] &new{2011-07-20 (水) 19:33:29};
- Web Startでもう一度実行してみましたが、やはり出来ませんでした。MouseEventで複数選択ha -- [[nsby]] &new{2011-07-22 (金) 15:59:14};
- あ、変な所で切れてしまいました。すみません。あらためて、MouseEventで複数選択出来るのは、Shift+クリックで選択した場合のみです。それ意外はダメでした。(Cntl+クリックとかでもダメ) -- [[nsby]] &new{2011-07-22 (金) 16:02:20};
-- Web Startのキャッシュは、…関係なさそうですね。src.zipをダウンロードしてJList#processMouseEvent(...)内で、System.out.println(e);したりsuper.processMouseEvent(convertMouseEvent(e));だけにしてみるとどうなるでしょうか? -- [[aterai]] &new{2011-07-24 (日) 07:58:36};

#comment