TITLE:JScrollPaneのViewPortをマウスで掴んでスクロール
#navi(../)
#tags()
RIGHT:Posted by &author(aterai); at 2006-01-02
*JScrollPaneのViewPortをマウスで掴んでスクロール [#ef47828b]
JScrollPaneの窓の中をマウスで掴んで画像をスクロールします。

-&jnlp;
-&jar;
-&zip;

//#screenshot
#ref(http://lh6.ggpht.com/_9Z4BYR88imo/TQTNqjajfcI/AAAAAAAAAbI/Km-h7tWdYOo/s800/HandScroll.png)

**サンプルコード [#e92a8d9e]
#code(link){{
class HandScrollListener extends MouseInputAdapter {
  Cursor defCursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
  Cursor hndCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
  Point pp = new Point();
  @Override public void mouseDragged(final MouseEvent e) {
    Point cp = e.getPoint();
    Point vp = vport.getViewPosition(); //= SwingUtilities.convertPoint(vport,0,0,label);
    vp.translate(pp.x-cp.x, pp.y-cp.y);
    //vport.setViewPosition(vp);
    label.scrollRectToVisible(
      new Rectangle(vp, vport.getSize()));
    pp.setLocation(cp);
  }
  @Override public void mousePressed(MouseEvent e) {
    label.setCursor(hndCursor);
    pp.setLocation(e.getPoint());
  }
  @Override public void mouseReleased(MouseEvent e) {
    label.setCursor(defCursor);
    label.repaint();
  }
}
}}

**解説 [#bf42cf21]
JViewportの原点(左上)を %%SwingUtilities.convertPointメソッドを使って中のJLabel(画像)の座標に変換し、これを基準座標としています。この座標を%% マウスの移動に応じて変更し、JComponent#scrollRectToVisibleメソッドの引数として使用することで、覗き窓のスクロールを行っています。

----
JComponent#scrollRectToVisible(...)ではなく、JViewport#setViewPosition(Point)を使用すると、内部コンポーネントの外側に移動することができます。

**参考リンク [#b337b5bb]
-[[JScrollPaneのオートスクロール>Swing/AutoScroll]]
-[http://sozai-free.com/ 2000ピクセル以上のフリー写真素材集]
--大きな''猫''写真があったので拝借しています。
-[http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6333318 Bug ID: 6333318 JViewPort.scrollRectToVisible( Rectangle cr ) doesn't scroll if cr left or above]
-[[JScrollPaneでキネティックスクロール>Swing/KineticScrolling]]
-[[JTreeの余白をドラッグしてスクロール>Swing/TreeDragScroll]]

**コメント [#ubd1d4e0]
- つかんで移動ということですが、移動方向が逆の気がします。 -- [[名無し]] &new{2006-02-25 (土) 01:24:46};
-- ご指摘ありがとうございます。確かに逆ですね。画像を掴んでというより、スクロールバーを掴んでみたいな動きになってました。修正しておきます。 -- [[aterai]] &new{2006-02-25 (土) 03:33:50};
- SwingUtilities.convertPointの代わりに、vport.getViewPosition()を使用するように変更。スクリーンショットの更新。 -- [[aterai]] &new{2009-01-19 (Mon) 16:58:27};
- JDK 1.7.0 では、JViewport#setViewPosition(Point)を使って右下外部に移動できなくなっている。HeavyweightとLightweightコンポーネントが混在しても問題ないようにするために、内部でrevalidate()しているのが原因? このサンプルではLightweightコンポーネントしか使用しないので、revalidate()しないように対応。 -- [[aterai]] &new{2011-10-03 (月) 18:03:55};

#comment