• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:JScrollBarのButtonの位置を変更
#navi(../)
RIGHT:Posted by &author(aterai); at 2011-05-16
*JScrollBarのButtonの位置を変更 [#jc858a4e]
JScrollBarのButtonの位置を変更します。
---
category: swing
folder: ScrollBarButtonLayout
title: JScrollBarのButtonの位置を変更
tags: [JScrollPane, JScrollBar, ArrowButton, LayoutManager]
author: aterai
pubdate: 2011-05-16T15:08:24+09:00
description: JScrollBarのスクロール移動Buttonの配置位置をレイアウトマネージャーを使って変更します。
image: https://lh6.googleusercontent.com/_9Z4BYR88imo/TdC-jTZ434I/AAAAAAAAA7I/cnbdjlwODJg/s800/ScrollBarButtonLayout.png
---
* 概要 [#summary]
`JScrollBar`のスクロール移動`Button`の配置位置をレイアウトマネージャーを使って変更します。

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

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

**サンプルコード [#r9d9f851]
* サンプルコード [#sourcecode]
#code(link){{
scrollbar.setUI(new WindowsScrollBarUI() {
  //Quote from javax.swing.plaf.basic.BasicScrollBarUI
  // 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 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 ---->
    // need before 1.7.0 ---->
    int decrGap = 0; //ins
    int incrGap = 0; //ins
    //incrGap = UIManager.getInt("ScrollBar.incrementButtonGap");
    //decrGap = UIManager.getInt("ScrollBar.decrementButtonGap");
    // 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
    // float value = getValue(sb); // del
    float value = sb.getValue(); // ins

    int thumbH = (range <= 0) ? getMaximumThumbSize().height
                              : (int)(trackH * (extent / range));
                              : (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())) {
    if (value < (sb.getMaximum() - sb.getVisibleAmount())) {
      float thumbRange = trackH - thumbH;
      thumbY = (int)(0.5f + (thumbRange * ((value - min) / (range - extent))));
      //thumbY +=  decrButtonY + decrButtonH + decrGap; //del
      thumbY = (int) (.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) {
    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 = decrButtonY + decrButtonH + decrGap; // del
    // int itrackH = incrButtonY - incrGap - itrackY; // del
    int itrackY = 0; //ins
    int itrackH = decrButtonY - itrackY; //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) {
    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) {
    } 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;
      if (thumbY < 0) { // (decrButtonY + decrButtonH + decrGap)) {
        thumbY = 1; // decrButtonY + decrButtonH + decrGap + 1;
      }
      setThumbBounds(itemX, thumbY, itemW, thumbH);
    }
  }
});
}}

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

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

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

#comment