更改 JSlider 的缩略图和颜色?

Change thumb and color of JSlider?

我正在创建一个音乐播放器程序。

我使用 JSlider

创建了搜索栏

代码:

JSlider seek = new JSlider(JProgressBar.HORIZONTAL);  
seek.setOpaque(true);

seek.setMajorTickSpacing(0);
seek.setMinorTickSpacing(0);
 
seek.setBackground(Color.DARK_GRAY);
seek.setSize(100, 13);
seek.setLocation(6, 30);

目前,它看起来像这样:

我只能用setBackground()方法改变JSlider的背景。

我不知道如何更改拇指颜色、拇指形状、轨道颜色等

我希望我的搜索栏看起来像这样:

我怎样才能做到这一点?

如果 JSlider 做不到,是否可以创建一个具有可滑动拇指的 JProgressBar

正如评论中已经提到的,如果不扩展 SliderUI 的现有实现,您无法更改滑块的外观。这是一个示例实现,说明如何从您的演示图片中获得视觉效果。

请注意,对尺寸和颜色进行硬编码并不是最好的方法,对于真正的实施,应该通过设置和使用 UIManager 可用的值来处理。

class Scratch {
    public static void main(final String[] args) {
        SwingUtilities.invokeLater(() -> {
            JPanel content = new JPanel(new BorderLayout());
            content.setPreferredSize(new Dimension(300, 100));
            JSlider slider = new JSlider() {
                @Override
                public void updateUI() {
                    setUI(new CustomSliderUI(this));
                }
            };
            content.add(slider);

            JFrame frame = new JFrame();
            frame.setContentPane(content);
            frame.pack();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }

    private static class CustomSliderUI extends BasicSliderUI {

        private static final int TRACK_HEIGHT = 8;
        private static final int TRACK_WIDTH = 8;
        private static final int TRACK_ARC = 5;
        private static final Dimension THUMB_SIZE = new Dimension(20, 20);
        private final RoundRectangle2D.Float trackShape = new RoundRectangle2D.Float();

        public CustomSliderUI(final JSlider b) {
            super(b);
        }

        @Override
        protected void calculateTrackRect() {
            super.calculateTrackRect();
            if (isHorizontal()) {
                trackRect.y = trackRect.y + (trackRect.height - TRACK_HEIGHT) / 2;
                trackRect.height = TRACK_HEIGHT;
            } else {
                trackRect.x = trackRect.x + (trackRect.width - TRACK_WIDTH) / 2;
                trackRect.width = TRACK_WIDTH;
            }
            trackShape.setRoundRect(trackRect.x, trackRect.y, trackRect.width, trackRect.height, TRACK_ARC, TRACK_ARC);
        }

        @Override
        protected void calculateThumbLocation() {
            super.calculateThumbLocation();
            if (isHorizontal()) {
                thumbRect.y = trackRect.y + (trackRect.height - thumbRect.height) / 2;
            } else {
                thumbRect.x = trackRect.x + (trackRect.width - thumbRect.width) / 2;
            }
        }

        @Override
        protected Dimension getThumbSize() {
            return THUMB_SIZE;
        }

        private boolean isHorizontal() {
            return slider.getOrientation() == JSlider.HORIZONTAL;
        }

        @Override
        public void paint(final Graphics g, final JComponent c) {
            ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            super.paint(g, c);
        }

        @Override
        public void paintTrack(final Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            Shape clip = g2.getClip();

            boolean horizontal = isHorizontal();
            boolean inverted = slider.getInverted();

            // Paint shadow.
            g2.setColor(new Color(170, 170 ,170));
            g2.fill(trackShape);

            // Paint track background.
            g2.setColor(new Color(200, 200 ,200));
            g2.setClip(trackShape);
            trackShape.y += 1;
            g2.fill(trackShape);
            trackShape.y = trackRect.y;

            g2.setClip(clip);

            // Paint selected track.
            if (horizontal) {
                boolean ltr = slider.getComponentOrientation().isLeftToRight();
                if (ltr) inverted = !inverted;
                int thumbPos = thumbRect.x + thumbRect.width / 2;
                if (inverted) {
                    g2.clipRect(0, 0, thumbPos, slider.getHeight());
                } else {
                    g2.clipRect(thumbPos, 0, slider.getWidth() - thumbPos, slider.getHeight());
                }

            } else {
                int thumbPos = thumbRect.y + thumbRect.height / 2;
                if (inverted) {
                    g2.clipRect(0, 0, slider.getHeight(), thumbPos);
                } else {
                    g2.clipRect(0, thumbPos, slider.getWidth(), slider.getHeight() - thumbPos);
                }
            }
            g2.setColor(Color.ORANGE);
            g2.fill(trackShape);
            g2.setClip(clip);
        }

        @Override
        public void paintThumb(final Graphics g) {
            g.setColor(new Color(246, 146, 36));
            g.fillOval(thumbRect.x, thumbRect.y, thumbRect.width, thumbRect.height);
        }

        @Override
        public void paintFocus(final Graphics g) {}
    }
}

结果: