I run several times into the situation where I needed to hardcode a JSlider tick spacing into my program. I always found it difficult to define the tick spacing because a good looking tick spacing depends on the current size of the JSlider on screen and its maximum value.
For my purposes I created a short function that automatically sets a "good looking" tick spacing (labels do not cover more than half of the slider width and use familiar spacing values like 1,2,5,10,20,50,...).
I wanted to share this little piece of code with you, maybe it helps someone...
Here it is:
private void setMajorTickSpacing(JSlider slider, int maxValue) {
Graphics graphics = slider.getGraphics();
FontMetrics fontMetrics = graphics.getFontMetrics();
int width = slider.getWidth();
// try with the following values:
// 1,2,5,10,20,50,100,200,500,...
int tickSpacing = 1;
for (int i = 0, tmpWidthSum = width + 1; tmpWidthSum > (width / 2);
i++) {
tickSpacing = (int) Math.pow(10, (i / 3));
switch (i % 3) {
case 1:
tickSpacing *= 2;
break;
case 2:
tickSpacing *= 5;
}
tmpWidthSum = 0;
for (int j = 0; j < maxValue; j += tickSpacing) {
Rectangle2D stringBounds = fontMetrics.getStringBounds(
String.valueOf(j), graphics);
tmpWidthSum += (int) stringBounds.getWidth();
if (tmpWidthSum > (width / 2)) {
// the labels are longer than the slider
break;
}
}
}
slider.setMajorTickSpacing(tickSpacing);
slider.setLabelTable(createLabels(slider, tickSpacing));
}
To have your tick spacing dynamically adopted when the user resizes the window, you should use a code snippet similar to the following one:
jSlider.addComponentListener(new java.awt.event.ComponentAdapter() {
public void componentResized(java.awt.event.ComponentEvent evt) {
setMajorTickSpacing(jSlider, maxValue);
}
});
There is still room for improvement, like handling minimum values etc.
Feel free to improve the code. And please share it with us! :-)