概要

JSliderの値を減少、増加するJButtonを作成してその左右に配置します。

スクリーンショット

Swing/SliderWithArrowButtons.png

サンプルコード

JSlider slider = new JSlider(-900, 900, 0);
slider.setMajorTickSpacing(10);
// slider.setPaintTicks(true);
slider.setSnapToTicks(true);
slider.setPaintLabels(true);
updateSliderLabelTable(slider);

JLabel label = new JLabel("100%", SwingConstants.CENTER) {
  @Override public Dimension getPreferredSize() {
    Dimension d = super.getPreferredSize();
    d.width = Math.max(d.width, 32);
    return d;
  }
};
slider.addChangeListener(e -> {
  int iv = slider.getValue();
  int pct;
  if (iv >= 0) {
    pct = 100 + iv;
    slider.setMajorTickSpacing(1);
  } else {
    pct = 100 + iv / 10;
    slider.setMajorTickSpacing(10);
  }
  label.setText(pct + "%");
  label.repaint();
});

View in GitHub: Java, Kotlin

解説

  • JSliderの値が0の場合は100%を表現し、ここが中央になるよう最小値を-900、最大値を900に設定
    • JSliderのノブをダブルクリックして値を初期値にリセットする
    • JSliderの値が正の場合は拡大を表現するよう、値を100 + JSlider#getValue()パーセントに変換してJLabelに表示(最大値は1000%になる)
    • JSliderの値が負の場合は縮小を表現するよう、値を100 + JSlider#getValue() / 10パーセントに変換してJLabelに表示(最小値は10%になる)
  • JButtonActionListenerではなくMouseListenerを追加し、プレスされている間はTimerを起動してJSliderの値を繰り返し増減する
class AutoRepeatHandler extends MouseAdapter implements ActionListener {
  private final Timer autoRepeatTimer;
  private final int stepSize;
  private final JSlider slider;
  private JButton arrowButton;

  protected AutoRepeatHandler(int stepSize, JSlider slider) {
    super();
    this.stepSize = stepSize;
    this.slider = slider;
    autoRepeatTimer = new Timer(60, this);
    autoRepeatTimer.setInitialDelay(300);
  }

  @Override public void actionPerformed(ActionEvent e) {
    Object o = e.getSource();
    if (o instanceof Timer) {
      boolean isPressed = arrowButton != null && !arrowButton.getModel().isPressed();
      if (isPressed && autoRepeatTimer.isRunning()) {
        autoRepeatTimer.stop();
        arrowButton = null;
      }
    } else if (o instanceof JButton) {
      arrowButton = (JButton) o;
    }
    int iv = slider.getValue();
    int step;
    if (iv == 0) {
      step = stepSize > 0 ? stepSize * 2 : stepSize * 10;
    } else if (iv > 0) {
      step = stepSize * 2;
    } else {
      step = stepSize * 10;
    }
    slider.setValue(iv + step);
  }

  @Override public void mousePressed(MouseEvent e) {
    if (SwingUtilities.isLeftMouseButton(e) && e.getComponent().isEnabled()) {
      autoRepeatTimer.start();
    }
  }

  @Override public void mouseReleased(MouseEvent e) {
    autoRepeatTimer.stop();
    arrowButton = null;
  }

  @Override public void mouseExited(MouseEvent e) {
    if (autoRepeatTimer.isRunning()) {
      autoRepeatTimer.stop();
    }
  }
}

参考リンク

コメント