I want to create a JSlider with only four possible values: 10 (min), 30, 60, and 100 (max). Is it possible to create one that can "snap" to only these values? If so, can you please provide an example? Thanks!
Asked
Active
Viewed 2,145 times
2
-
Is there a reason you want to have inconsistent incremented ticks? 10,40,70,100 doesn't meet your need? – JBuenoJr Jul 30 '13 at 00:09
-
1Yes you can. You'll need a custom `DefaultBoundedRangeModel` to manage the values and a implementation of the `BasicSliderUI` to manage the stepping...about there I stopped trying... – MadProgrammer Jul 30 '13 at 00:26
2 Answers
5
The following example is probably the easiest way to do what you're looking for. Note that you can't simply override getValue() on the JSlider subclass to return the domain-specific value, because that is problematic for the underlying JSlider/BasicSliderUI implementation. In this example, I've defined a custom getDomainValue() to return the domain-specific value (10, 30, 60, or 100) based on the slider tick position.
package example.stackoverflow;
import java.util.Hashtable;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class SteppingSliderExample
{
public static class SteppingSlider extends JSlider
{
private static final long serialVersionUID = -1195270044097152629L;
private static final Integer[] VALUES = { 10, 30, 60, 100 };
private static final Hashtable<Integer, JLabel> LABELS = new Hashtable<>();
static
{
for(int i = 0; i < VALUES.length; ++i)
{
LABELS.put(i, new JLabel(VALUES[i].toString()));
}
}
public SteppingSlider()
{
super(0, VALUES.length - 1, 0);
setLabelTable(LABELS);
setPaintTicks(true);
setPaintLabels(true);
setSnapToTicks(true);
setMajorTickSpacing(1);
}
public int getDomainValue()
{
return VALUES[getValue()];
}
}
public static void createAndShowGUI()
{
JFrame frame = new JFrame("SteppingSlider");
frame.setSize(500, 120);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final SteppingSlider steppingSlider = new SteppingSlider();
final String labelPrefix = "Slider value: ";
final JLabel output = new JLabel(labelPrefix + steppingSlider.getDomainValue());
steppingSlider.addChangeListener(new ChangeListener()
{
@Override
public void stateChanged(ChangeEvent evt)
{
output.setText(labelPrefix + steppingSlider.getDomainValue());
}
});
frame.getContentPane().setLayout(
new BoxLayout(frame.getContentPane(),
BoxLayout.Y_AXIS));
frame.getContentPane().add(steppingSlider);
frame.getContentPane().add(output);
frame.setVisible(true);
}
public static void main(String[] args) throws Exception
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}

Buzz Killington
- 1,039
- 9
- 14
-
Your example is exactly what I was looking for! Thanks for showing me how to do it. :) – BJ Dela Cruz Jul 30 '13 at 04:23
-1
Write a subclass of JSlider that overrides getValue() and maps e.g. [1,2,3,4] (original) to [10,30,60,100]. Simplest solution that comes to my mind.
-
1This is very dangerous as this will change the functionality of the `JSlider` (it internally also accesses it's `getValue()` method). – brimborium Nov 23 '15 at 22:52