Swing/GridScrollAnimation のバックアップ(No.3)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/GridScrollAnimation へ行く。
  - 1 (2012-08-13 (月) 16:28:05)
- 2 (2012-08-14 (火) 19:58:11)
- 3 (2012-12-07 (金) 18:08:41)
- 4 (2012-12-25 (火) 18:23:14)
- 5 (2014-12-12 (金) 15:16:35)
- 6 (2015-03-01 (日) 16:07:40)
- 7 (2017-01-13 (金) 15:16:17)
- 8 (2017-12-15 (金) 14:23:26)
- 9 (2019-07-09 (火) 13:44:45)
- 10 (2019-11-04 (月) 01:58:19)
- 11 (2021-05-27 (木) 16:29:37)
- 12 (2025-01-03 (金) 08:57:02)
- 13 (2025-01-03 (金) 09:01:23)
- 14 (2025-01-03 (金) 09:02:38)
- 15 (2025-01-03 (金) 09:03:21)
- 16 (2025-01-03 (金) 09:04:02)
- 17 (2025-06-19 (木) 12:41:37)
- 18 (2025-06-19 (木) 12:43:47)
 
TITLE:GridLayoutとJScrollPaneを使ったグリッド単位での表示切り替え
Posted by aterai at 2012-08-13
GridLayoutとJScrollPaneを使ったグリッド単位での表示切り替え
JPanelにGridLayoutでコンポーネントを追加し、これをJScrollPaneに配置して、グリッド単位での表示、スクロールアニメーションによる切り替えを行います。
- &jnlp;
- &jar;
- &zip;
サンプルコード
class GridPanel extends JPanel implements Scrollable {
  public static int cols = 3, rows = 4;
  public static Dimension size = new Dimension(160*cols, 120*rows);
  public GridPanel() {
    super(new GridLayout(rows, cols, 0, 0));
    //putClientProperty("JScrollBar.fastWheelScrolling", Boolean.FALSE);
  }
  @Override public Dimension getPreferredScrollableViewportSize() {
    Dimension d = getPreferredSize();
    return new Dimension(d.width/cols, d.height/rows);
  }
  @Override public int getScrollableUnitIncrement(
      Rectangle visibleRect, int orientation, int direction) {
    return orientation==SwingConstants.HORIZONTAL ?
      visibleRect.width : visibleRect.height;
  }
  @Override public int getScrollableBlockIncrement(
      Rectangle visibleRect, int orientation, int direction) {
    return orientation==SwingConstants.HORIZONTAL ?
      visibleRect.width : visibleRect.height;
  }
  @Override public boolean getScrollableTracksViewportWidth() {
    return false;
  }
  @Override public boolean getScrollableTracksViewportHeight() {
    return false;
  }
  @Override public Dimension getPreferredSize() {
    return size;
  }
}
class ScrollAction extends AbstractAction {
  private static Timer scroller;
  private final Point vec;
  private final JScrollPane scrollPane;
  public ScrollAction(String name, JScrollPane scrollPane, Point vec) {
    super(name);
    this.scrollPane = scrollPane;
    this.vec = vec;
  }
  @Override public void actionPerformed(ActionEvent e) {
    final JViewport vport = scrollPane.getViewport();
    final JComponent v = (JComponent)vport.getView();
    final int w   = vport.getWidth(),
              h   = vport.getHeight(),
              sx  = vport.getViewPosition().x,
              sy  = vport.getViewPosition().y;
    final Rectangle rect = new Rectangle(w, h);
    if(scroller!=null && scroller.isRunning()) return;
    scroller = new Timer(5, new ActionListener() {
      double MAX = 100d;
      int count = (int)MAX;
      @Override public void actionPerformed(ActionEvent e) {
        double a = easeInOut(--count/MAX);
        int dx = (int)(w - a*w + 0.5d);
        int dy = (int)(h - a*h + 0.5d);
        if(count<=0) {
          dx = w;
          dy = h;
          scroller.stop();
        }
        rect.setLocation(sx + vec.x * dx, sy + vec.y * dy);
        v.scrollRectToVisible(rect);
      }
    });
    scroller.start();
  }
  private static double easeInOut(double t) {
    //range: 0.0<=t<=1.0
    if(t<0.5d) {
      return 0.5d*pow3(t*2d);
    } else {
      return 0.5d*(pow3(t*2d-2d) + 2d);
    }
  }
  private static double pow3(double a) {
    //return Math.pow(a, 3d);
    return a * a * a;
  }
}
解説
上記のサンプルでは、GridLayoutを使ってグリッド状に配置したコンポーネントを、JScrollPaneとscrollRectToVisible(...)メソッドで、グリッド単位の表示と切り替え(スクロールアニメーション付き)を行なっています。
- 最初に表示されるコンポーネントは、左上にある(一番最初にJPanelに追加した)コンポーネント
- PreferredScrollableViewportSize の変更(グリッドのサイズ変更)には対応していない
- JScrollPaneの各スクロールバーは常に非表示なので、マウスホイールによるスクロールには対応していない
- フォーカスの移動に表示切り替えは対応していない
- CardLayout+スクロールアニメーションでも同様の動作が可能?
