Swing/CursorOfCellComponent のバックアップ差分(No.3)
- バックアップ一覧
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- バックアップ を表示
- Swing/CursorOfCellComponent へ行く。
- 追加された行はこの色です。
- 削除された行はこの色です。
--- title: JListのセル中に配置したコンポーネント毎にカーソルを変更する tags: [JList, Cursor, ListCellRenderer] author: aterai pubdate: 2013-10-21T00:16:35+09:00 description: JListのセルに配置されているコンポーネントをマウスの座標から検索し、それに設定されたカーソルをJListに適用します。 --- * 概要 [#l0ef8c80] `JList`のセルに配置されているコンポーネントをマウスの座標から検索し、それに設定されたカーソルを`JList`に適用します。 #download(https://lh3.googleusercontent.com/-v3ugRz81Y0Q/UmPxM3SwOYI/AAAAAAAAB4Y/PqZaNMCPgN0/s800/CursorOfCellComponent.png) * サンプルコード [#bbc6a488] #code(link){{ JList<String> list = new JList<String>(model) { private LinkCellRenderer renderer; class LinkCellList<E> extends JList<E> { private int prevIndex = -1; public LinkCellList(ListModel<E> model) { super(model); } @Override public void updateUI() { setForeground(null); setBackground(null); setSelectionForeground(null); setSelectionBackground(null); super.updateUI(); renderer = new LinkCellRenderer(); setCellRenderer(renderer); setFixedCellHeight(32); setCellRenderer(new LinkCellRenderer<E>()); } private int prevIndex = -1; @Override protected void processMouseMotionEvent(MouseEvent e) { Point pt = e.getPoint(); int i = locationToIndex(pt); String s = ((ListModel<String>)getModel()).getElementAt(i); E s = ((ListModel<E>) getModel()).getElementAt(i); Component c = getCellRenderer().getListCellRendererComponent( this, s, i, false, false); Rectangle r = getCellBounds(i, i); c.setBounds(r); if(prevIndex!=i) { if (prevIndex != i) { c.doLayout(); } prevIndex = i; pt.translate(-r.x, -r.y); Component cmp = SwingUtilities.getDeepestComponentAt(c, pt.x, pt.y); if(cmp != null) { if (cmp == null) { setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } else { setCursor(cmp.getCursor()); }else{ setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } } }; } }} * 解説 [#eef2a91f] 上記のサンプルでは、以下の手順でイベントを取得しないセルレンダラー中のコンポーネントに応じたカーソルの変更を行っています。 - `JList`上をマウスカーソルを移動した時に、カーソルのある行を取得 - セルレンダラーに行番号や文字列などの値を渡して描画用のコンポーネントを取得 - 描画用コンポーネントの位置とサイズを`JList#getCellBounds()`で取得したセル領域に変更 -- `Component#setBounds(...)`で描画用コンポーネントの位置とサイズを変更してもその子コンポーネントのレイアウトは更新されない - `Component#doLayout()`で、レイアウトを更新 -- このサンプルで使用している`FlowLayout`では、`JLabel`に設定する文字列の長さで後続のコンポーネントの位置が変化するので、`Component#doLayout()`が必要 -- ただし、同じ行の場合は描画用コンポーネントも前回と同じはずなのでレイアウトを更新する必要はない -- [[JListのセル内にJButtonを配置する>Swing/ButtonsInListCell]]などのように、すべての行のレイアウトが同じ(内容に応じて変化しない)場合も同様に更新する必要はない - `JList`基準のカーソル座標を描画用コンポーネント基準に変更 - `SwingUtilities.getDeepestComponentAt(...);`で描画用コンポーネントから変更した座標の下にある子コンポーネントを取得 - 取得した子コンポーネントのカーソルを`JList`のカーソルとして設定 //* 参考リンク * コメント [#qc093f08] #comment #comment