如何使用 Nimubs L&F 将 JSlider 轨道填充到当前拇指值的点?

How to fill JSlider track up to the point of the current thumb value with Nimubs L&F?

我正在研究音量滑块,想更改 Nimbus 的默认外观 JSlider

我希望我的 JSlider 自动填充曲目直到当前拇指值的点。这种方法的一个想法就像(见图)

我曾尝试扩展 BasicSliderUI 并重写 paintTrack() 方法,但没有成功。我也试过为 JSlider 设置皮肤(参见示例 http://www.jasperpotts.com/blog/2008/08/skinning-a-slider-with-nimbus/),但似乎这种方法只改变了 JSlider.

的外观

有人知道如何解决这个问题吗?

此示例仅支持水平 JSlider:

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

public class SliderSkinDemo2 {
  public JComponent makeUI() {
    UIDefaults d = new UIDefaults();
    d.put("Slider:SliderTrack[Enabled].backgroundPainter", new Painter<JSlider>() {
      @Override public void paint(Graphics2D g, JSlider c, int w, int h) {
        int arc         = 10;
        int trackHeight = 8;
        int trackWidth  = w - 2;
        int fillTop     = 4;
        int fillLeft    = 1;

        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                           RenderingHints.VALUE_ANTIALIAS_ON);
        g.setStroke(new BasicStroke(1.5f));
        g.setColor(Color.GRAY);
        g.fillRoundRect(fillLeft, fillTop, trackWidth, trackHeight, arc, arc);

        int fillBottom = fillTop + trackHeight;
        int fillRight  = xPositionForValue(
            c.getValue(), c,
            new Rectangle(fillLeft, fillTop, trackWidth, fillBottom - fillTop));

        g.setColor(Color.ORANGE);
        g.fillRect(fillLeft + 1, fillTop + 1, fillRight - fillLeft, fillBottom - fillTop);

        g.setColor(Color.WHITE);
        g.drawRoundRect(fillLeft, fillTop, trackWidth, trackHeight, arc, arc);
      }
      //@see javax/swing/plaf/basic/BasicSliderUI#xPositionForValue(int value)
      protected int xPositionForValue(int value, JSlider slider, Rectangle trackRect) {
        int min = slider.getMinimum();
        int max = slider.getMaximum();
        int trackLength = trackRect.width;
        double valueRange = (double) max - (double) min;
        double pixelsPerValue = (double) trackLength / valueRange;
        int trackLeft = trackRect.x;
        int trackRight = trackRect.x + (trackRect.width - 1);
        int xPosition;

        xPosition = trackLeft;
        xPosition += Math.round(pixelsPerValue * ((double) value - min));

        xPosition = Math.max(trackLeft, xPosition);
        xPosition = Math.min(trackRight, xPosition);

        return xPosition;
      }
    });

    JSlider slider = new JSlider();
    slider.putClientProperty("Nimbus.Overrides", d);

    JPanel p = new JPanel();
    p.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
    p.setBackground(Color.DARK_GRAY);
    p.add(new JSlider());
    p.add(Box.createRigidArea(new Dimension(200, 20)));
    p.add(slider);
    return p;
  }
  public static void main(String... args) {
    EventQueue.invokeLater(() -> {
      try {
        for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
          if ("Nimbus".equals(laf.getName())) {
            UIManager.setLookAndFeel(laf.getClassName());
          }
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new SliderSkinDemo2().makeUI());
      f.setSize(320, 240);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}