JSlider滑块图标的绘制

9

我想重新涂色JSlider的标记或滑块,而不是标准的灰色。我该如何实现?

3个回答

19
扩展 BasicSliderUI 代理并不是没有风险的,但正如下面的示例所建议的那样,它确实允许对呈现进行任意控制。

BasicSliderUI subclass image

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

2
我使用了这段代码,但发现它需要处理禁用状态,因此我添加了这段代码来降低颜色条的饱和度:if (!this.slider.isEnabled()) for (int i=0 ; i<colors.length ; i++) { float[] hsv = Color.RGBtoHSB(colors[i].getRed(),colors[i].getGreen(),colors[i].getBlue(),null); colors[i] = new Color(Color.HSBtoRGB(hsv[0], 0.25f, hsv[2])); } - AZDean
1
惊人的强大且简洁呈现!谢谢! - JFreeman

9

有三种方法:

  1. 更改 Java外观, 首选方式
  2. 覆盖XxxSliderUI,但这将是外观敏感的,不是简单的方法
  3. 学习Synth外观

使用Synth的示例

Synth slider

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文件

<?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

在TrashGod非常有帮助的答案上进行扩展,我添加了几行代码,使得该条形图可以填充到您移动它的位置。其余部分将为空白:

输入图片描述

实现这一点的代码如下:

Original Answer翻译成"最初的回答"

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

    // ...

}

如果你想要一个背景颜色,可以在绘制第一个矩形之前先绘制第二个矩形:

enter image description here

最初的回答。
    // ... 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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接