Is there a way to increase the resolution of a Java Swing JSlider when dragging the knob?

34 Views Asked by At

In my Java application, I have a couple JSliders that cover a very wide range, say -16384 to + 32767. Resolution when dragging the knob is something like 250. If I select the knob I can increment it by +/- 1 with the arrow keys but that is ridiculously slow. I think I've seen implementations (not necessarily Java Swing) where you can hold down a key and then the knob slider increments are much smaller. I'm looking for an example of this in action or some suggestion as to how to go about it.

So far all I've done is to read through the documentation here:

https://docs.oracle.com/javase/tutorial/uiswing/components/slider.html

TIA,

DL

1

There are 1 best solutions below

3
aterai On

There are several possible methods, such as setting JSlider#setSnapToTicks(true); JSlider#setMajorTickSpacing() or performing a negative/positiveBlockIncrement action instead of a negative/positiveUnitIncrement action on the key pressed.

import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;

public final class SliderUnitIncrementTest {
  private Component makeUI() {
    JSlider slider0 = new JSlider(-16384, 32767);
    slider0.setSnapToTicks(true);
    // slider0.setMinorTickSpacing(0);
    slider0.setMajorTickSpacing(1638);

    JSlider slider1 = new JSlider(-16384, 32767);
    InputMap im = slider1.getInputMap();
    // negativeBlockIncrement PAGE_DOWN, ctrl PAGE_DOWN
    // positiveBlockIncrement PAGE_UP, ctrl PAGE_UP
    KeyStroke left = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0);
    im.put(left, "negativeBlockIncrement");
    KeyStroke right = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0);
    im.put(right, "positiveBlockIncrement");

    // negativeUnitIncrement LEFT, KP_LEFT, DOWN, KP_DOWN
    // positiveUnitIncrement RIGHT, KP_RIGHT, UP, KP_UP
    im.put(KeyStroke.getKeyStroke("ctrl LEFT"), "negativeUnitIncrement");
    im.put(KeyStroke.getKeyStroke("ctrl RIGHT"), "positiveUnitIncrement");

    JPanel p = new JPanel(new GridLayout(2, 1, 64, 64));
    p.add(slider0);
    p.add(slider1);
    JPanel panel = new JPanel(new BorderLayout());
    panel.add(p, BorderLayout.NORTH);
    panel.setBorder(BorderFactory.createEmptyBorder(32, 64, 0, 64));
    return panel;
  }

  public static void main(String[] args) {
    EventQueue.invokeLater(() -> {
      JFrame frame = new JFrame("@title@");
      frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      frame.getContentPane().add(new SliderUnitIncrementTest().makeUI());
      frame.setSize(320, 240);
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
    });
  }
}