概要

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

サンプルコード

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

解説

JViewportの原点(左上)をマウスの移動に応じて変更し、JComponent#scrollRectToVisibleメソッドの引数として使用して覗き窓のスクロールを行っています。

  • JComponent#scrollRectToVisible(...)ではなくJViewport#setViewPosition(Point)を使用すると内部コンポーネントの外側に移動可能

// // 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);

参考リンク

コメント