Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this a bug in JSlider?

I've been having some problems using the JSlider class - specifically with tick labels.

The first time I use setMajorTickSpacing and setMinorTickSpacing everything works as expected. However, subsequent calls to setMajorTickSpacing update the ticks, but not the labels. I've written a simple example to demonstrate this behaviour:

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

public class SliderTest {
    public static void main(String args[]) {
        JFrame frame = new JFrame();
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent we) {
                System.exit(0);
            }
        });
        frame.setSize(300, 250);

        JSlider slider = new JSlider(0, 100, 0);
        slider.setMajorTickSpacing(10);
        slider.setMinorTickSpacing(1);
        slider.setPaintLabels(true);
        slider.setPaintTicks(true);

        slider.setMajorTickSpacing(25);
        slider.setMinorTickSpacing(5);

        frame.add(slider);
        frame.pack();
        frame.setVisible(true);
    }
}

Two simple work-arounds seem to fix the problem - either using slider.setLabelTable(null) or slider.setLabelTable(slider.createStandardLabels(25)) before the second call to setMajorTickSpacing. Given this, it would seem that the label table is not being updated correctly.

I'm not sure if this is the intended behaviour or not. My first instinct is that updating the tick spacing should also update the labels, but there are also arguments for separating the two.

So I'd like to know which it is - is this a bug in JSlider or the intended behaviour? If it is the intended behaviour, what would be the standout reasons for making that choice?

like image 227
charlemagne Avatar asked Sep 24 '12 09:09

charlemagne


1 Answers

You can easily see the cause of this problem by looking into setMajorTickSpacing source code:

public void setMajorTickSpacing(int n) {
    int oldValue = majorTickSpacing;
    majorTickSpacing = n;
    if ( labelTable == null && getMajorTickSpacing() > 0 && getPaintLabels() ) {
        setLabelTable( createStandardLabels( getMajorTickSpacing() ) );
    }
    firePropertyChange("majorTickSpacing", oldValue, majorTickSpacing);
    if (majorTickSpacing != oldValue && getPaintTicks()) {
        repaint();
    }
}

If you call this method twice - labelTable value won't be null anymore and it won't be updated. It might be an intended behavior according to method's comment:

 * This method will also set up a label table for you.
 * If there is not already a label table, and the major tick spacing is
 * {@code > 0}, and {@code getPaintLabels} returns
 * {@code true}, a standard label table will be generated (by calling
 * {@code createStandardLabels}) with labels at the major tick marks.

So you have to update labels manually each time you want them to be updated (unless you override this method with your own that does the update).

like image 116
Mikle Garin Avatar answered Nov 09 '22 17:11

Mikle Garin