6

I have a little problem with my JSlider, that I haven't been able to solve. To explain the situation a little, I have to do a JSlider going from 0 to 20, through 0.1 steps. I tricked my way out of problems by creating a JSlider from 0 to 200, and redefined the labels under the slider to display the corrent percentages instead of the integer values.

But I have one last problem : I'm using a custom L&F (that I can't change, obviously, as it is from the client), that displays the value over the slider thumb. However, this value is displayed...in its standard way, as an integer. From what I've been able to grasp, this display is related to the Slider.paintValue property, as I can see in javax.swing.plaf.synth.SynthSliderUI source code. However, I've been dramatically unable to remove it.

What I've tried for now :

UIManager.getLookAndFeelDefaults().put("Slider.paintValue", false);
UIManager.put("Slider.paintValue", false);

None of those two changed anything.

Is there a Swing guru around here who could get me out of this ?

Valentin Rocher
  • 11,343
  • 43
  • 59
  • Hmm, I can't really do that, as this is commercial code. Besides, the only thing I do is creating a JSlider, and then trying to set it. SSCCE does not really applies here. – Valentin Rocher Dec 17 '10 at 15:49

2 Answers2

4

I just created a demo with a JSlider and using the basic Synth LAF, and I can confirm that setting those properties appears to have no effect at all, which is odd, and very annoying too.

I have looked at SynthSliderUI and I can see the protected boolean paintValue being set in private void updateStyle(JSlider c), so if you were to make a custom extension this class, set the value of paintValue to false, and then set your slider's UI to the new UI with setUI(), you might get closer. Either that, or completely override the paint methods, copying code out of the original but removing the part that paints the thumb value.

Now, SynthSliderUI itself is package-private, but that isn't really the issue anyway since you're using a client-provided LAF. If their custom slider UI class is public and non-final, you can make a hacked version as I described above, and apply it to your slider.

If it's final, then you might be able to use reflection to change that paintValue field as a last resort (maybe just before painting your slider). The following hack works for me (take out the reflection call that sets the field to false to see the thumb value being painted):

import java.awt.BorderLayout;
import java.lang.reflect.Field;

import javax.swing.JFrame;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

public class SliderDemo {

    public static void main(String[] args) throws Exception {
        UIManager.setLookAndFeel("javax.swing.plaf.synth.SynthLookAndFeel");

        Class<?> sliderUIClass = Class.forName("javax.swing.plaf.synth.SynthSliderUI");
        final Field paintValue = sliderUIClass.getDeclaredField("paintValue");
        paintValue.setAccessible(true);

        SwingUtilities.invokeAndWait(new Runnable() {
            @Override
            public void run() {
                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setLayout(new BorderLayout());

                JSlider slider = new JSlider(3, 6, 4);
                try {
                    paintValue.set(slider.getUI(), false);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                f.add(slider, BorderLayout.CENTER);

                f.pack();
                f.setVisible(true);
            }
        });
    }

}
BoffinBrain
  • 5,697
  • 5
  • 28
  • 53
  • Holy crap, why couldn't I think of using reflection to do this ? I think your solution might work. As soon as I've got the time to test it, I'll tell you and mark the question answered :) – Valentin Rocher Dec 17 '10 at 15:50
  • Man, you really saved my life on this. So sorry not to be able to put a bounty on this question, I really would have loved to give you a little more rep. After answering many questions here, this is one of the first I've asked, and I'm so happy. Thanks again ! – Valentin Rocher Dec 17 '10 at 15:55
  • No problem. :) It's scary how often Reflection comes to the rescue in these kinds of situations! – BoffinBrain Dec 20 '10 at 14:27
4

Calling UIManager.put("Slider.paintValue", false) before the call to initComponents() worked for me.

jacknad
  • 12,453
  • 38
  • 115
  • 190