TITLE:JScrollPaneのViewPortをマウスで掴んでスクロール

Posted by at 2006-01-02

JScrollPaneのViewPortをマウスで掴んでスクロール

`JScrollPane`の窓の中をマウスで掴んで画像をスクロールします。

  • &jnlp;
  • &jar;
  • &zip;
HandScroll.png

サンプルコード

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();
  }
}
View in GitHub: Java, Kotlin

解説

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


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

参考リンク

コメント

  • つかんで移動ということですが、移動方向が逆の気がします。 -- 名無し
    • ご指摘ありがとうございます。確かに逆ですね。画像を掴んでというより、スクロールバーを掴んでみたいな動きになってました。修正しておきます。 -- aterai
  • `SwingUtilities.convertPointの代わりに、vport.getViewPosition()`を使用するように変更。スクリーンショットの更新。 -- aterai
  • `JDK 1.7.0では、JViewport#setViewPosition(Point)を使って右下外部に移動できなくなっている。HeavyweightLightweightコンポーネントが混在しても問題ないようにするために、内部でrevalidate()しているのが原因? このサンプルではLightweightコンポーネントしか使用しないので、revalidate()`しないように対応。 -- aterai
  • サンプルほしい --