• category: swing folder: SnapToTicksDrag title: JSliderのSnapToTicksをマウスのドラッグでも適用する tags: [JSlider, MouseMotionListener] author: aterai pubdate: 2009-12-14T13:49:28+09:00 description: JSliderのSnapToTicksをマウスでのドラッグ中にも適用されるように設定します。 image: https://lh6.googleusercontent.com/_9Z4BYR88imo/TQTTU-ruijI/AAAAAAAAAkM/p3Mze4pjyEk/s800/SnapToTicksDrag.png hreflang:
       href: http://java-swing-tips.blogspot.com/2009/12/snap-to-ticks-drag-jslider.html
       lang: en

概要

JSliderSnapToTicksをマウスでのドラッグ中にも適用されるように設定します。

サンプルコード

slider.setUI(new MetalSliderUI() {
  @Override protected TrackListener createTrackListener(final JSlider slider) {
    return new TrackListener() {
      @Override public void mouseDragged(MouseEvent e) {
        if (!slider.getSnapToTicks() || slider.getMajorTickSpacing() == 0) {
          super.mouseDragged(e);
          return;
        }
        //case SwingConstants.HORIZONTAL:
        int halfThumbWidth = thumbRect.width / 2;
        final int trackLength = trackRect.width;
        final int trackLeft   = trackRect.x - halfThumbWidth;
        final int trackRight  = trackRect.x + trackRect.width - 1 + halfThumbWidth;
        int xPos = e.getX();
        int snappedPos = xPos;
        if (xPos <= trackLeft) {
          snappedPos = trackLeft;
        } else if (xPos >= trackRight) {
          snappedPos = trackRight;
        } 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 / actualPixelsForOneTick) * actualPixelsForOneTick + .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);
      }
    };
  }
});
View in GitHub: Java, Kotlin

解説

  • 上: Default SnapToTicks
    • slider.setSnapToTicks(true);としているので、マウスをリリースした時点で、ノブを置いた位置にもっとも近い目盛にスナップされる
  • 下: Custom SnapToTicks
    • TrackListener#mouseDraggedをオーバーライドして、マウスでドラッグ中でもカーソルからもっとも近い目盛にスナップされる

コメント