Juliane Juliane - 4 months ago 24
Java Question

JSlider image behind track

I want to put an image (visualization of an audio) behind the JSlider which represents the audioplayer, the process of playing.
First I tried to overwrite the paint-method of the Slider

public void paintComponent(Graphics g) {
// Draw the previously loaded image to Component
g.drawImage(img, 0, -100, null);

this worked, but the image is higher than the slider, so my next try was a JLayeredPane, where I put the JSlider above a JLabel with the image. Looks good for the first moment. But I mentioned that I need the image behind the track of the slider, not the whole slider. There is space to the left and right. Can anybody tell me a way how to calculate this space? Or the width and offset of the track to the border of the slider? This should run under Windows and MacOs, so different LookAndFeels, so I think hard coded values will not work.
Example Slider with background image



My solution for this Problem is now to overwrite the SliderUI. So this is a very special component, so it's nonrelevant that it looks the same on all LookAndFeels. It supports also jumping directly to mouse position, which is different to BasicSliderUI.

 * Custom SliderUI for AudioPlayer with audioimage in background
public class AudioSliderUI extends BasicSliderUI {

    private BasicStroke stroke = new BasicStroke(1f, BasicStroke.CAP_ROUND, 
            BasicStroke.JOIN_ROUND, 0f);

    public AudioSliderUI(AudioSlider b) {

    public void paint(Graphics g, JComponent c) {
        Graphics2D g2d = (Graphics2D) g;
        super.paint(g, c);

    protected Dimension getThumbSize() {
        return new Dimension(2, 200);

    public void paintTrack(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        Stroke old = g2d.getStroke();
        if (slider.getOrientation() == SwingConstants.HORIZONTAL) {
            g2d.drawLine(trackRect.x, trackRect.y + trackRect.height / 2, 
                    trackRect.x + trackRect.width, trackRect.y + trackRect.height / 2);
        } else {
            g2d.drawLine(trackRect.x + trackRect.width / 2, trackRect.y, 
                    trackRect.x + trackRect.width / 2, trackRect.y + trackRect.height);
        Image img = ((AudioSlider)slider).getImage();
        g2d.drawImage(img, trackRect.x, trackRect.y, trackRect.width, trackRect.height, slider);


    public void paintThumb(Graphics g) {
        Rectangle knobBounds = thumbRect;
        int w = knobBounds.width;
        int h = 100;
        int newStarty = knobBounds.height/2- h/2;
        g.translate(knobBounds.x, knobBounds.y);

        //     "plain" version
        g.fillRect(0, newStarty, w, h);


    protected TrackListener createTrackListener(JSlider slider) {
        return new TrackListener() {
            public void mousePressed(MouseEvent e) {
                if (UIManager.getBoolean("Slider.onlyLeftMouseButtonDrag")
                        && SwingUtilities.isLeftMouseButton(e)) {
                    JSlider slider = (JSlider) e.getComponent();
                    switch (slider.getOrientation()) {
                    case SwingConstants.VERTICAL:
                    case SwingConstants.HORIZONTAL:
                        throw new IllegalArgumentException(
                                "orientation must be one of: VERTICAL, HORIZONTAL");
                    super.mousePressed(e); // isDragging = true;
                } else {

            public boolean shouldScroll(int direction) {
                return false;

Matching Slider:

public class AudioSlider extends JSlider {

    private Image img;

    public AudioSlider() {

     * @return the img
    public Image getImage() {
        return img;

    public void setImage(Image img) {
        this.img = img;

Works for me, maybe covers not all prospects.