JScrollBar上にマウスカーソルが入ったらその幅を拡張する
Total: 1534
, Today: 2
, Yesterday: 2
Posted by aterai at
Last-modified:
概要
JScrollBar
上へのマウスカーソルの出入りをJLayer
で取得してその幅を拡大・縮小します。
Screenshot
Advertisement
サンプルコード
JScrollPane scroll = new JScrollPane(makeList());
scroll.setHorizontalScrollBarPolicy(
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
JPanel controls = new JPanel();
Timer animator = new Timer(10, e -> controls.revalidate());
controls.setLayout(new BorderLayout(0, 0) {
private int controlsWidth = MIN_WIDTH;
@Override public Dimension preferredLayoutSize(Container target) {
Dimension ps = super.preferredLayoutSize(target);
int controlsPreferredWidth = ps.width;
if (animator.isRunning()) {
if (willExpand) {
if (controls.getWidth() < controlsPreferredWidth) {
controlsWidth += 1;
}
} else {
if (controls.getWidth() > MIN_WIDTH) {
controlsWidth -= 1;
}
}
if (controlsWidth <= MIN_WIDTH) {
controlsWidth = MIN_WIDTH;
animator.stop();
} else if (controlsWidth >= controlsPreferredWidth) {
controlsWidth = controlsPreferredWidth;
animator.stop();
}
}
ps.width = controlsWidth;
return ps;
}
});
controls.add(scroll.getVerticalScrollBar());
JPanel p = new JPanel(new BorderLayout());
p.add(controls, BorderLayout.EAST);
p.add(scroll);
JPanel pp = new JPanel(new GridLayout(1, 2));
pp.add(new JLayer<>(p, new LayerUI<JPanel>() {
private boolean isDragging;
@Override public void installUI(JComponent c) {
super.installUI(c);
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(
AWTEvent.MOUSE_EVENT_MASK
| AWTEvent.MOUSE_MOTION_EVENT_MASK);
}
}
@Override public void uninstallUI(JComponent c) {
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(0);
}
super.uninstallUI(c);
}
@Override protected void processMouseMotionEvent(
MouseEvent e, JLayer<? extends JPanel> l) {
int id = e.getID();
Component c = e.getComponent();
if (c instanceof JScrollBar && id == MouseEvent.MOUSE_DRAGGED) {
isDragging = true;
}
}
@Override protected void processMouseEvent(
MouseEvent e, JLayer<? extends JPanel> l) {
if (e.getComponent() instanceof JScrollBar) {
switch (e.getID()) {
case MouseEvent.MOUSE_ENTERED:
if (!animator.isRunning() && !isDragging) {
willExpand = true;
animator.setInitialDelay(0);
animator.start();
}
break;
case MouseEvent.MOUSE_EXITED:
if (!animator.isRunning() && !isDragging) {
willExpand = false;
animator.setInitialDelay(500);
animator.start();
}
break;
case MouseEvent.MOUSE_RELEASED:
isDragging = false;
if (!animator.isRunning()
&& !e.getComponent().getBounds().contains(e.getPoint())) {
willExpand = false;
animator.setInitialDelay(500);
animator.start();
}
break;
default:
break;
}
l.getView().repaint();
}
}
}));
pp.add(new JLayer<>(
makeTranslucentScrollBar(makeList()),
new ScrollBarOnHoverLayerUI()));
View in GitHub: Java, Kotlin解説
- 左:
JPanel
にJScrollPane
と縦JScrollBar
を分けて配置JPanel
に縦JScrollBar
の幅をTimer
を使用して拡大・縮小するレイアウトマネージャを設定JPanel
をJLayer
でラップして縦JScrollBar
へのマウスカーソルの出入りなどを検知MouseEvent.MOUSE_ENTERED
とMouseEvent.MOUSE_EXITED
で出入りを検知してTimer
を起動する- ただしマウスドラッグ中でも
MouseEvent.MOUSE_ENTERED
とMouseEvent.MOUSE_EXITED
イベントが発生する場合があるのでMouseEvent.MOUSE_DRAGGED
中はTimer
を起動しない MouseEvent.MOUSE_RELEASED
イベントが発生したとき縦JScrollBar
内にマウスカーソルがある場合はTimer
を起動しない(幅を拡大した状態を維持する)
- 縦
JScrollBar
の幅を縮小する場合500
ミリ秒ウェイトを入れてすぐにTimer
を起動しないよう設定
- 右:
- 縦
JScrollBar
の矢印ボタンを非表示に設定 - マウスカーソルの出入りで縦
JScrollBar
の色と幅を変更
- 縦