Swing/HandScroll の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/HandScroll へ行く。
- Swing/HandScroll の差分を削除
--- category: swing folder: HandScroll title: JScrollPaneのViewportをマウスで掴んでスクロール tags: [JScrollPane, JViewport, MouseListener, MouseMotionListener, JLabel] author: aterai pubdate: 2006-01-02T06:45:45+09:00 description: JScrollPaneの窓の中をマウスで掴んで画像をスクロールします。 image: https://lh6.googleusercontent.com/_9Z4BYR88imo/TQTNqjajfcI/AAAAAAAAAbI/Km-h7tWdYOo/s800/HandScroll.png hreflang: href: https://java-swing-tips.blogspot.com/2009/03/mouse-dragging-viewport-scroll.html lang: en --- * 概要 [#summary] `JScrollPane`の窓の中をマウスで掴んで画像をスクロールします。 #download(https://lh6.googleusercontent.com/_9Z4BYR88imo/TQTNqjajfcI/AAAAAAAAAbI/Km-h7tWdYOo/s800/HandScroll.png) * サンプルコード [#sourcecode] #code(link){{ class HandScrollListener extends MouseAdapter { private final Cursor defCursor = Cursor.getDefaultCursor(); private final Cursor hndCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); private final Point pp = new Point(); @Override public void mouseDragged(MouseEvent e) { JViewport vport = (JViewport) e.getComponent(); Point cp = e.getPoint(); Point vp = vport.getViewPosition(); // = SwingUtilities.convertPoint(vport, 0, 0, label); vp.translate(pp.x - cp.x, pp.y - cp.y); // if (r1.isSelected()) { label.scrollRectToVisible(new Rectangle(vp, vport.getSize())); // } else { // vport.setViewPosition(vp); // } pp.setLocation(cp); } @Override public void mousePressed(MouseEvent e) { e.getComponent().setCursor(hndCursor); pp.setLocation(e.getPoint()); } @Override public void mouseReleased(MouseEvent e) { e.getComponent().setCursor(defCursor); } } }} * 解説 [#explanation] `JViewport`の原点(左上)をマウスの移動に応じて変更し、`JComponent#scrollRectToVisible`メソッドの引数として使用して覗き窓のスクロールを行っています。 - `JComponent#scrollRectToVisible(...)`ではなく`JViewport#setViewPosition(Point)`を使用すると内部コンポーネントの外側に移動可能 ---- - [https://bugs.openjdk.org/browse/JDK-6333318 JDK-6333318 JViewPort.scrollRectToVisible( Rectangle cr ) doesn't scroll if cr left or above - Java Bug System] -- `JDK 1.7.0`から、`JViewport#setViewPosition(Point)`などで左上外部などの枠外に移動不可になっている -- 左上外部は`Java 11`で修正された?、右下外部は移動不可のまま --- [https://bugs.openjdk.org/browse/JDK-8195738 JDK-8195738 scroll position in ScrollPane is reset after calling validate() - Java Bug System] -- 以下のように`JViewport#revalidate()`をオーバーライドして枠外スクロールは可能に戻せるが、親`JFrame`をリサイズすると表示位置はリセットされる #code{{ // // JDK 1.6.0 // JScrollPane scroll = new JScrollPane(label); // JViewport vport = scroll.getViewport(); // JDK 1.7.0 or later JViewport vport = new JViewport() { private static final boolean WEIGHT_MIXING = false; private boolean isAdjusting; @Override public void revalidate() { if (!WEIGHT_MIXING && isAdjusting) { return; } super.revalidate(); } @Override public void setViewPosition(Point p) { if (WEIGHT_MIXING) { super.setViewPosition(p); } else { isAdjusting = true; super.setViewPosition(p); isAdjusting = false; } } }; vport.add(label); JScrollPane scroll = new JScrollPane(); scroll.setViewport(vport); }} * 参考リンク [#reference] - [[JScrollPaneのオートスクロール>Swing/AutoScroll]] - [http://sozai-free.com/ 2000ピクセル以上のフリー写真素材集] -- 猫の写真を引用 - [https://bugs.openjdk.org/browse/JDK-6333318 JDK-6333318 JViewPort.scrollRectToVisible( Rectangle cr ) doesn't scroll if cr left or above - Java Bug System] -- [https://bugs.openjdk.org/browse/JDK-8195738 JDK-8195738 scroll position in ScrollPane is reset after calling validate() - Java Bug System] - [[JScrollPaneでキネティックスクロール>Swing/KineticScrolling]] - [[JTreeの余白をドラッグしてスクロール>Swing/TreeDragScroll]] * コメント [#comment] #comment - つかんで移動ということですが、移動方向が逆の気がします。 -- &user(名無し); &new{2006-02-25 (土) 01:24:46}; -- ご指摘ありがとうございます。確かに逆ですね。画像を掴んでというより、スクロールバーを掴んでみたいな動きになってました。修正しておきます。 -- &user(aterai); &new{2006-02-25 (土) 03:33:50}; - `SwingUtilities.convertPoint`の代わりに、`vport.getViewPosition()`を使用するように変更。スクリーンショットの更新。 -- &user(aterai); &new{2009-01-19 (Mon) 16:58:27}; - `JDK 1.7.0`では、`JViewport#setViewPosition(Point)`を使って%%右下%%左上外部に移動できなくなっている。`Heavyweight`と`Lightweight`コンポーネントが混在しても問題ないようにするために、内部で`revalidate()`しているのが原因? このサンプルでは`Lightweight`コンポーネントしか使用しないので、`revalidate()`しないように対応。 -- &user(aterai); &new{2011-10-03 (月) 18:03:55}; - サンプルほしい -- &new{2013-05-11 (土) 03:30:34}; -- ページ上部にソースコードなどへのリンクがあるので、使ってみてください。上げ忘れてるとかメンテ中などでなければダウンロードできると思います。 -- &user(aterai); &new{2013-05-13 (月) 20:08:18}; #comment