• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:JSliderのSnapToTicksをマウスのドラッグでも適用する
#navi(../)
RIGHT:Posted by [[terai]] at 2009-12-14
*JSliderのSnapToTicksをマウスのドラッグでも適用する [#ec2028a2]
JSliderのSnapToTicksをマウスでのドラッグ中にも適用されるように設定します。

-&jnlp;
-&jar;
-&zip;

#screenshot

**サンプルコード [#hccb5c20]
#code{{
slider.setUI(new MetalSliderUI() {
  protected TrackListener createTrackListener(final JSlider slider) {
    return new TrackListener() {
      public void mouseDragged(MouseEvent e) {
        //case JSlider.HORIZONTAL:
        int halfThumbWidth = thumbRect.width / 2;
        int halfThumbWidth    = thumbRect.width / 2;
        int trackLength = trackRect.width;
        int trackLeft   = trackRect.x - halfThumbWidth;
        int trackRight  = trackRect.x + (trackRect.width - 1) + halfThumbWidth;
        int trackLeft  = trackRect.x-halfThumbWidth;
        int trackRight = trackRect.x+(trackRect.width-1)+halfThumbWidth;
        int xPos = e.getX();
        int snappedPos = xPos;
        if(xPos <= trackLeft) {
        if (xPos < = trackLeft) {
          snappedPos = trackLeft;
        }else if(xPos >= trackRight) {
        } else if (xPos > = trackRight) {
          snappedPos = trackRight;
        }else{
          int tickSpacing = slider.getMajorTickSpacing();
          float temp = trackLength * tickSpacing / (float)slider.getMaximum();
        } else {
          //int tickSpacing = slider.getMajorTickSpacing();
          //float actualPixelsForOneTick = trackLength * tickSpacing
          //                                 / (float)slider.getMaximum();
          // a problem if you choose to set a negative MINIMUM for
          // the JSlider; the calculated drag-positions are wrong.
          // Fixed by bobndrew:
          int possibleTickPositions=slider.getMaximum()-slider.getMinimum();
          int tickSpacing = (slider.getMinorTickSpacing()==0)
                            ? slider.getMajorTickSpacing()
                            : slider.getMinorTickSpacing();
          float actualPixelsForOneTick = trackLength * tickSpacing
                                         / (float)possibleTickPositions;
          xPos -= trackLeft;
          snappedPos = (int)((Math.round(xPos/temp) * temp) + 0.5) + trackLeft;
          snappedPos=(int)((Math.round(xPos/temp)*temp)+0.5)+trackLeft;
          offset = 0;
          //System.out.println(snappedPos);
        }
        MouseEvent me = new MouseEvent(
          e.getComponent(), e.getID(), e.getWhen(), e.getModifiers(),
          snappedPos, e.getY(),
          e.getXOnScreen(), e.getYOnScreen(),
          e.getClickCount(), e.isPopupTrigger(), e.getButton());
        e.consume();
        super.mouseDragged(me);
      }
    };
  }
});
}}

**解説 [#idd12036]
-上:デフォルト
--slider.setSnapToTicks(true);としているので、マウスをリリースした時点で、ノブを置いた位置にもっとも近い目盛にスナップされる
-下:
--TrackListener#mouseDraggedをオーバーライドして、マウスでドラッグ中でもカーソルからもっとも近い目盛にスナップされる

//**参考リンク
**コメント [#h246efdc]
- JSlider.HORIZONTAL にしか対応していません。 -- [[terai]] &new{2009-12-21 (月) 11:01:51};
- bobndrewさんからの指摘で、ミニマムにマイナスの値を入れるとおかしくなるバグ修正と、MinorTickSpacingに対応。 -- [[terai]] &new{2010-10-26 (火) 15:32:11};

#comment