• 追加された行はこの色です。
  • 削除された行はこの色です。
---
title: JScrollBarのButtonの位置を変更
tags: [JScrollPane, JScrollBar, ArrowButton]
tags: [JScrollPane, JScrollBar, ArrowButton, LayoutManager]
author: aterai
pubdate: 2011-05-16T15:08:24+09:00
description: JScrollBarのButtonの位置を変更します。
description: JScrollBarのスクロール移動Buttonの配置位置をレイアウトマネージャーを使って変更します。
---
* 概要 [#jc858a4e]
`JScrollBar`の`Button`の位置を変更します。
`JScrollBar`のスクロール移動`Button`の配置位置をレイアウトマネージャーを使って変更します。

#download(https://lh6.googleusercontent.com/_9Z4BYR88imo/TdC-jTZ434I/AAAAAAAAA7I/cnbdjlwODJg/s800/ScrollBarButtonLayout.png)

* サンプルコード [#r9d9f851]
#code(link){{
scrollbar.setUI(new WindowsScrollBarUI() {
  //Quote from javax.swing.plaf.basic.BasicScrollBarUI
  @Override protected void layoutVScrollbar(JScrollBar sb) {
    Dimension sbSize = sb.getSize();
    Insets sbInsets = sb.getInsets();

    /*
     * Width and left edge of the buttons and thumb.
     */
    int itemW = sbSize.width - (sbInsets.left + sbInsets.right);
    int itemX = sbInsets.left;

    /* Nominal locations of the buttons, assuming their preferred
     * size will fit.
     */
    boolean squareButtons = false;
    //DefaultLookup.getBoolean(scrollbar, this, "ScrollBar.squareButtons", false);
    int decrButtonH = squareButtons
      ? itemW : decrButton.getPreferredSize().height;
    int incrButtonH = squareButtons
      ? itemW : incrButton.getPreferredSize().height;

    //int decrButtonY = sbInsets.top;
    int decrButtonY = sbSize.height - (sbInsets.bottom + incrButtonH + decrButtonH);
    int incrButtonY = sbSize.height - (sbInsets.bottom + incrButtonH);

    /* The thumb must fit within the height left over after we
     * subtract the preferredSize of the buttons and the insets
     * and the gaps
     */
    int sbInsetsH = sbInsets.top + sbInsets.bottom;
    int sbButtonsH = decrButtonH + incrButtonH;

    //need before 1.7.0 ---->
    int decrGap = 0; //ins
    int incrGap = 0; //ins
    //incrGap = UIManager.getInt("ScrollBar.incrementButtonGap");
    //decrGap = UIManager.getInt("ScrollBar.decrementButtonGap");
    //<----

    int gaps = decrGap + incrGap;
    float trackH = sbSize.height - (sbInsetsH + sbButtonsH) - gaps;

    /* Compute the height and origin of the thumb.   The case
     * where the thumb is at the bottom edge is handled specially
     * to avoid numerical problems in computing thumbY.  Enforce
     * the thumbs min/max dimensions.  If the thumb doesn't
     * fit in the track (trackH) we'll hide it later.
     */
    float min = sb.getMinimum();
    float extent = sb.getVisibleAmount();
    float range = sb.getMaximum() - min;
    //float value = getValue(sb); //del
    float value = sb.getValue(); //ins

    int thumbH = (range <= 0) ? getMaximumThumbSize().height
                              : (int)(trackH * (extent / range));
    thumbH = Math.max(thumbH, getMinimumThumbSize().height);
    thumbH = Math.min(thumbH, getMaximumThumbSize().height);

    int thumbY = incrButtonY - incrGap - thumbH;
    if(value < (sb.getMaximum() - sb.getVisibleAmount())) {
      float thumbRange = trackH - thumbH;
      thumbY = (int)(0.5f + (thumbRange * ((value - min) / (range - extent))));
      //thumbY +=  decrButtonY + decrButtonH + decrGap; //del
    }

    /* If the buttons don't fit, allocate half of the available
     * space to each and move the lower one (incrButton) down.
     */
    int sbAvailButtonH = (sbSize.height - sbInsetsH);
    if(sbAvailButtonH < sbButtonsH) {
      incrButtonH = decrButtonH = sbAvailButtonH / 2;
      incrButtonY = sbSize.height - (sbInsets.bottom + incrButtonH);
    }
    decrButton.setBounds(itemX, decrButtonY, itemW, decrButtonH);
    incrButton.setBounds(itemX, incrButtonY, itemW, incrButtonH);

    /* Update the trackRect field.
     */
    //int itrackY = decrButtonY + decrButtonH + decrGap; //del
    //int itrackH = incrButtonY - incrGap - itrackY; //del
    int itrackY = 0; //ins
    int itrackH = decrButtonY - itrackY; //ins
    trackRect.setBounds(itemX, itrackY, itemW, itrackH);

    /* If the thumb isn't going to fit, zero it's bounds.  Otherwise
     * make sure it fits between the buttons.  Note that setting the
     * thumbs bounds will cause a repaint.
     */
    if(thumbH >= (int) trackH) {
      setThumbBounds(0, 0, 0, 0);
    }else{
      //if((thumbY + thumbH) > incrButtonY - incrGap) {
      //  thumbY = incrButtonY - incrGap - thumbH;
      //}
      //if(thumbY < (decrButtonY + decrButtonH + decrGap)) {
      //  thumbY = decrButtonY + decrButtonH + decrGap + 1;
      //}
      if((thumbY + thumbH) > decrButtonY - decrGap) {
        thumbY = decrButtonY - decrGap - thumbH;
      }
      if(thumbY < 0) { //(decrButtonY + decrButtonH + decrGap)) {
        thumbY = 1; //decrButtonY + decrButtonH + decrGap + 1;
      }
      setThumbBounds(itemX, thumbY, itemW, thumbH);
    }
  }
});
}}

* 解説 [#aa7d754c]
上記のサンプルでは、`WindowsScrollBarUI#layoutVScrollbar(...)`をオーバーライドして、垂直スクロールバーの増加、減少ボタンが両方下側に配置されるようにレイアウトマネージャーを変更しています。

* 参考リンク [#s7eb814a]
-- [[JScrollBarをJScrollPaneの左と上に配置>Swing/LeftScrollBar]]
-- スクロールバーのボタンの位置ではなく、スクロールバー自体の位置を変更する場合のサンプル

* コメント [#p4024b2d]
#comment
- 水平スクロールバーには今のところ対応していない。 -- &user(aterai); &new{2011-05-16 (月) 15:08:24};

#comment