JListのセル中に配置したコンポーネント毎にカーソルを変更する
Total: 4795
, Today: 2
, Yesterday: 1
Posted by aterai at
Last-modified:
概要
JList
のセルに配置されているコンポーネントをマウスの座標から検索し、それに設定されたカーソルをJList
に適用します。
Screenshot
Advertisement
サンプルコード
class LinkCellList<E> extends JList<E> {
private int prevIndex = -1;
protected LinkCellList(ListModel<E> model) {
super(model);
}
@Override public void updateUI() {
setForeground(null);
setBackground(null);
setSelectionForeground(null);
setSelectionBackground(null);
super.updateUI();
setFixedCellHeight(32);
setCellRenderer(new LinkCellRenderer<>());
// TEST: putClientProperty("List.isFileList", Boolean.TRUE);
}
@Override protected void processMouseMotionEvent(MouseEvent e) {
Point pt = e.getPoint();
int i = locationToIndex(pt);
E s = getModel().getElementAt(i);
Component c = getCellRenderer().getListCellRendererComponent(
this, s, i, false, false);
Rectangle r = getCellBounds(i, i);
c.setBounds(r);
if (prevIndex != i) {
c.doLayout();
}
prevIndex = i;
pt.translate(-r.x, -r.y);
setCursor(
Optional.ofNullable(SwingUtilities.getDeepestComponentAt(c, pt.x, pt.y))
.map(Component::getCursor)
.orElse(Cursor.getDefaultCursor()));
}
}
View in GitHub: Java, Kotlin解説
上記のサンプルでは、以下の手順でイベントを取得しないセルレンダラー中のコンポーネントに応じたカーソルの変更を行っています。
JList
上をマウスカーソルを移動した時にカーソルのある行を取得- セルレンダラーに行番号や文字列などの値を渡して描画用のコンポーネントを取得
- 描画用コンポーネントの位置とサイズを
JList#getCellBounds()
で取得したセル領域に変更Component#setBounds(...)
で描画用コンポーネントの位置とサイズを変更してもその子コンポーネントのレイアウトは更新されない
Component#doLayout()
でレイアウトを更新- このサンプルで使用している
FlowLayout
ではJLabel
に設定する文字列の長さで後続のコンポーネントの位置が変化するのでComponent#doLayout()
を実行してレイアウトの更新を行う必要がある - ただし、同じ行の場合は描画用コンポーネントも前回と同じはずなのでレイアウトを更新する必要はない
- JListのセル内にJButtonを配置するのように、すべての行のレイアウトが同じ(内容に応じて変化しない)場合もレイアウトを更新する必要はない
- このサンプルで使用している
JList
基準のカーソル位置座標を描画用コンポーネント基準に変更SwingUtilities.getDeepestComponentAt(...)
メソッドで描画用コンポーネントから変更した座標の直下にある子コンポーネントを取得- 取得した子コンポーネントのカーソルを
JList
のカーソルとして設定
参考リンク
JListのセルレンダラーとして設定したJEditorPaneからHyperlinkEventを取得する