Swing/ChangeScrollBarWidthOnHover の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/ChangeScrollBarWidthOnHover へ行く。
- Swing/ChangeScrollBarWidthOnHover の差分を削除
--- category: swing folder: ChangeScrollBarWidthOnHover title: JScrollBar上にマウスカーソルが入ったらその幅を拡張する tags: [JScrollBar, JScrollPane, JLayer, LayoutManager, Animation] author: aterai pubdate: 2019-09-02T18:04:32+09:00 description: JScrollBar上へのマウスカーソルの出入りをJLayerで取得してその幅を拡大・縮小します。 image: https://drive.google.com/uc?id=1BAF8wRV7pfhmJTBiE9_cun0SbMVR2XFQ --- * 概要 [#summary] `JScrollBar`上へのマウスカーソルの出入りを`JLayer`で取得してその幅を拡大・縮小します。 #download(https://drive.google.com/uc?id=1BAF8wRV7pfhmJTBiE9_cun0SbMVR2XFQ) * サンプルコード [#sourcecode] #code(link){{ JScrollPane scroll = new JScrollPane(makeList()); scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 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())); pp.add(new JLayer<>( makeTranslucentScrollBar(makeList()), new ScrollBarOnHoverLayerUI())); }} * 解説 [#explanation] - 左: -- `JPanel`に`JScrollPane`と縦`JScrollBar`を分けて配置 -- `JPanel`に縦`JScrollBar`の幅を`Timer`を使用して拡大・縮小するレイアウトマネージャを設定 --- [[LayoutManagerを使ってパネルの展開アニメーションを行う>Swing/LayoutAnimation]] -- `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のArrowButtonを非表示にする>Swing/ArrowButtonlessScrollBar]] -- マウスカーソルの出入りで縦`JScrollBar`の色と幅を変更 --- [[JScrollBarをJTable上に重ねて表示するJScrollPaneを作成する>Swing/OverlappedScrollBar]] * 参考リンク [#reference] - [[JScrollPane上にマウスカーソルが存在する場合のみJScrollBarを表示する>Swing/ScrollBarOnHover]] * コメント [#comment] #comment #comment