Question

Im am trying to customize a jScrollPane using the code below. It works, It changes the color the way I want it, but hides the arrowbuttons.

What I want is to make them visible again and change them with a custom image. I tried searching on this forum, but I couldnt find any info about it.

I hope someone can help me. Thanks in advance!

    private Image imageThumb, imageTrack;
    private JButton b = new JButton() {
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(0, 0);
        }
    };

  public YourScrollbarUI () {
        imageThumb = WrapImage .create(45, 45, new Color(46,218,163));
        imageTrack = WrapImage .create(32, 32, new Color(90,90,90));
    }

    @Override
    protected void paintThumb(Graphics g, JComponent c, Rectangle r) {
        g.setColor(Color.blue);
        ((Graphics2D) g).drawImage(imageThumb,
                r.x, r.y, r.width, r.height, null);
    }

    @Override
    protected void paintTrack(Graphics g, JComponent c, Rectangle r) {
        ((Graphics2D) g).drawImage(imageTrack,
                r.x, r.y, r.width, r.height, null);
    }

    @Override
    protected JButton createDecreaseButton(int orientation) {
        return b;
    }

    @Override
    protected JButton createIncreaseButton(int orientation) {
        return b;
    }

private static class WrapImage {

    static public Image create(int w, int h, Color c) {
        BufferedImage bi = new BufferedImage(
                w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = bi.createGraphics();
        g2d.setPaint(c);
        g2d.fillRect(0, 0, w, h);
        g2d.dispose();
        return bi;}}
Was it helpful?

Solution

It changes the color the way I want it, but hides the arrowbuttons.

Here is the problem:

private JButton b = new JButton() {
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(0, 0); // why (0,0) ???
    }
};

In your code b button is the responsible for painting the arrows through createDecreaseButton and createIncreaseButton methods. If its preferred size is (0,0) then logically it won't be visible.

What I want is to make them visible again and change them with a custom image.

You need to modify createDecreaseButton and createIncreaseButton to make them return a new JButton with the desired icon.

Update

I already tried playing with the prefferedsize (making them the same size as the custom image), but the custom arrowimages are still not showing up. Im clueless

Look at this working example. MyScrollbarUI extends from BasicScrollBarUI just as your class does. You'll see the key is overrding the button's getPreferredSize() method and setting the appropriate icon as needed.

In this regard I should say BasicScrollBarUI.createDecreaseButton(int orientation) and BasicScrollBarUI.createIncreaseButton(int orientation) methods are poorly documented (there's no javadoc). But if you dive into this class using an IDE then you'll see orientation paramenter can take one of these values: SwingConstants.NORTH, SwingConstants.SOUTH, SwingConstants.EAST, SwingConstants.WEST. Keep this in mind when look at getAppropriateIcon(int orientation) method.

These are used icons: Up arrowDown arrowLeft arrowRight arrow

import java.awt.Dimension;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.plaf.basic.BasicScrollBarUI;

public class Demo {

    private void initGUI(){
        JScrollPane scrollPane = new JScrollPane(new JTextArea(10, 20));
        scrollPane.getHorizontalScrollBar().setUI(new MyScrollbarUI());
        scrollPane.getVerticalScrollBar().setUI(new MyScrollbarUI());

        JFrame frame = new JFrame("Demo");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(scrollPane);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {        
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Demo().initGUI();
            }
        });
    }

    class MyScrollbarUI extends BasicScrollBarUI {

        private ImageIcon downArrow, upArrow, leftArrow, rightArrow;

        public MyScrollbarUI(){
            try {
                upArrow = new ImageIcon(new java.net.URL("http://icons.iconarchive.com/icons/oxygen-icons.org/oxygen/16/Actions-arrow-up-icon.png"));
                downArrow = new ImageIcon(new java.net.URL("http://icons.iconarchive.com/icons/oxygen-icons.org/oxygen/16/Actions-arrow-down-icon.png"));
                rightArrow = new ImageIcon(new java.net.URL("http://icons.iconarchive.com/icons/oxygen-icons.org/oxygen/16/Actions-arrow-right-icon.png"));
                leftArrow = new ImageIcon(new java.net.URL("http://icons.iconarchive.com/icons/oxygen-icons.org/oxygen/16/Actions-arrow-left-icon.png"));
            } catch (java.net.MalformedURLException ex) {
                ex.printStackTrace();
            }        
        }

        @Override
        protected JButton createDecreaseButton(int orientation) {
            JButton decreaseButton = new JButton(getAppropriateIcon(orientation)){
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(22, 22);
                }
            };
            return decreaseButton;
        }

        @Override
        protected JButton createIncreaseButton(int orientation) {
            JButton increaseButton = new JButton(getAppropriateIcon(orientation)){
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(22, 22);
                }
            };
            return increaseButton;
        }

        private ImageIcon getAppropriateIcon(int orientation){
            switch(orientation){
                case SwingConstants.SOUTH: return downArrow;
                case SwingConstants.NORTH: return upArrow;
                case SwingConstants.EAST: return rightArrow;
                    default: return leftArrow;
            }
        }
    }    

}

Screenshot

enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top