开发者

Painting the slider icon of JSlider

Would like to repa开发者_C百科int the the marker or the thumb of the JSlider instead of the standard gray. How can I achieve this?


Extending the BasicSliderUI delegate is not without peril, but it does allow arbitrary control over the rendering, as suggested in the example below.

Painting the slider icon of JSlider

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);
    }
}


There are three ways:

  1. change Java Look and Feel, Preferred of Ways
  2. OverRide XxxSliderUI, but that would be Look and Feel sensitive, and not easy way
  3. learning The Synth Look and Feel

Example using Synth

Painting the slider icon of JSlider

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>


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:

Painting the slider icon of JSlider

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:

Painting the slider icon of JSlider

    // ... 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);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜