Would like to repaint the the marker or the thumb of the JSlider instead of the standard gray. How can I achieve this?
            Asked
            
        
        
            Active
            
        
            Viewed 1.1k times
        
    9
            
            
        
        Andrew Thompson
        
- 168,117
 - 40
 - 217
 - 433
 
        Jeetesh Nataraj
        
- 608
 - 2
 - 8
 - 20
 
3 Answers
19
            
            
        Extending the BasicSliderUI delegate is not without peril, but it does allow arbitrary control over the rendering, as suggested in the example below.

slider.setUI(new MySliderUI(slider));
...
private static class MySliderUI extends BasicSliderUI {
    private static float[] fracs = {0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f};
    private LinearGradientPaint p;
    public MySliderUI(JSlider slider) {
        super(slider);
    }
    @Override
    public void paintTrack(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        Rectangle t = trackRect;
        Point2D start = new Point2D.Float(t.x, t.y);
        Point2D end = new Point2D.Float(t.width, t.height);
        Color[] colors = {Color.magenta, Color.blue, Color.cyan,
            Color.green, Color.yellow, Color.red};
        p = new LinearGradientPaint(start, end, fracs, colors);
        g2d.setPaint(p);
        g2d.fillRect(t.x, t.y, t.width, t.height);
    }
    @Override
    public void paintThumb(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        Rectangle t = thumbRect;
        g2d.setColor(Color.black);
        int tw2 = t.width / 2;
        g2d.drawLine(t.x, t.y, t.x + t.width - 1, t.y);
        g2d.drawLine(t.x, t.y, t.x + tw2, t.y + t.height);
        g2d.drawLine(t.x + t.width - 1, t.y, t.x + tw2, t.y + t.height);
    }
}
        trashgod
        
- 203,806
 - 29
 - 246
 - 1,045
 
- 
                    2I used this code but found I needed it to handle being disabled, so I added this code to lower the saturation of the color bar: if (!this.slider.isEnabled()) for (int i=0 ; i
– AZDean Aug 19 '14 at 14:43  - 
                    1Amazingly powerful and simply presented! Thank you! – JFreeman Apr 14 '19 at 00:53
 
9
            There are three ways:
- change Java Look and Feel, 
Preferred of Ways - OverRide XxxSliderUI, but that would be Look and Feel sensitive, and not easy way
 - learning The Synth Look and Feel
 
Example using Synth

SynthSliderTest.java
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.synth.*;
public class SynthSliderTest {
    private JFrame f = new JFrame();
    public SynthSliderTest() {
        try {
            SynthLookAndFeel laf = new SynthLookAndFeel();
            laf.load(SynthSliderTest.class.getResourceAsStream("yourPathTo/demo.xml"), SynthSliderTest.class);
            UIManager.setLookAndFeel(laf);
        } catch (Exception e) {
            e.printStackTrace();
        }
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.getContentPane().add(makeUI());
        f.setSize(320, 240);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
    public JComponent makeUI() {
        JSlider slider = new JSlider(0, 100);
        JPanel p = new JPanel();
        p.add(slider);
        return p;
    }
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                SynthSliderTest synthSliderTest = new SynthSliderTest();
            }
        });
    }
}
demo.xml file
<?xml version="1.0" encoding="UTF-8"?>
<synth>
    <style id="backingStyle">
        <opaque value="TRUE"/>
        <font name="Dialog" size="12"/>
        <state>
            <color value="WHITE" type="BACKGROUND"/>
            <color value="BLACK" type="FOREGROUND"/>
        </state>
    </style>
    <bind style="backingStyle" type="region" key=".*"/>
    <style id="SliderTrackStyle">
        <opaque value="TRUE"/>
        <state>
            <color type="BACKGROUND" value="ORANGE"/>
        </state>
    </style>
    <bind style="SliderTrackStyle" type="region" key="SliderTrack" />
    <style id="SliderThumbStyle">
        <opaque value="TRUE"/>
        <state>
            <color type="BACKGROUND" value="RED"/>
        </state>
        <state value="PRESSED">
            <color type="BACKGROUND" value="GREEN"/>
        </state>
    <!-- state value="MOUSE_OVER">
      <color type="BACKGROUND" value="BLUE"/>
    </state -->
    </style>
    <bind style="SliderThumbStyle" type="region" key="SliderThumb" />
</synth>
2
            
            
        Expanding on TrashGod's very helpful answer, I added in a few lines of code to allow the bar to be filled up to the point in which you have moved it. The rest of the bar will be blank:
The code to do this is:
@Override
public void paintTrack(Graphics g) {
    // ... TrashGod's code ...
    // calculate how much of the progress bar to fill
    double percentage = (double)slider.getValue()/(double)slider.getMaximum();
    // fill the progress bar with a rectange of that size, (with curved corners of 4px diameter)
    g2d.fillRoundRect(t.x, t.y, (int)(t.width*percentage), t.height, 4, 4);
    // ...
}
And if you want a background color as well, paint a second rectange before you paint the first:
    // ... TrashGod's code ...
    // calculate how much of the progress bar to fill
    double percentage = (double)slider.getValue()/(double)slider.getMaximum();
    // PAINT THE BACKGROUND
    // create a gradient paint for the background
    p = new LinearGradientPaint(start, end, new float[] {0.4f,0.8f}, new Color[] {Color.gray.brighter(), Color.gray.brighter().brighter()});
    g2d.setPaint(p);
    g2d.fillRoundRect((int)(t.width*percentage), t.y, t.width - (int)(t.width*percentage), t.height, 4, 4);
    // PAINT THE FOREGROUND
    // create the gradient paint
    p = new LinearGradientPaint(start, end, fracs, colors);
    g2d.setPaint(p);
    // fill the progress bar with a rectange of that size, (with curved corners of 4px diameter)
    g2d.fillRoundRect(t.x, t.y, (int)(t.width*percentage), t.height, 4, 4);
        JFreeman
        
- 974
 - 1
 - 10
 - 26
 

