Java JScrollBar Design
Asked Answered
M

4

1

I want customize the JScrollBar Design. I use Mac to develop the app with eclipse. I already tried to scrollPane.getVerticalScrollBar().setBackground(Color.BLACK); but nothing happen.

My code:

scrollPane = new JScrollPane(scriptView);
scrollPane.setBorder(BorderFactory.createEmptyBorder());
scrollPane.getVerticalScrollBar().setUnitIncrement(6);
window.getContentPane().add(scrollPane);

The Object scriptView is from the class JEditorPane.

How it should look:

sample

Thanks for every help.

Malynda answered 4/5, 2013 at 10:48 Comment(2)
"How it should look:" I do not understand. I see no scrollbar in the screenshot.Gatewood
@AndrewThompson raises a crucial issue regarding visibility and usability, which you should consider in your ScrollBarUI design.Spinal
A
9

I guess you are looking for a transparent scrollbar.

enter image description here

This is just presented as an idea(NOT tested code):

import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.*;

public class TranslucentScrollBarTest {
  public JComponent makeUI() {
    JTextArea cmp = new JTextArea();
    String str = "1234567890abcdefghijklmnopqrstuvwxyz";
    for(int i=0; i<20; i++) {
      cmp.append(str+str+"\n");
    }
    cmp.setForeground(Color.WHITE);
    cmp.setBackground(Color.BLACK);
    cmp.setOpaque(true);

    JScrollPane scrollPane = new JScrollPane(
      cmp, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
      ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    scrollPane.setComponentZOrder(scrollPane.getVerticalScrollBar(), 0);
    scrollPane.setComponentZOrder(scrollPane.getViewport(), 1);
    scrollPane.getVerticalScrollBar().setOpaque(false);

    scrollPane.setLayout(new ScrollPaneLayout() {
      @Override
      public void layoutContainer(Container parent) {
        JScrollPane scrollPane = (JScrollPane)parent;

        Rectangle availR = scrollPane.getBounds();
        availR.x = availR.y = 0;

        Insets insets = parent.getInsets();
        availR.x = insets.left;
        availR.y = insets.top;
        availR.width  -= insets.left + insets.right;
        availR.height -= insets.top  + insets.bottom;

        Rectangle vsbR = new Rectangle();
        vsbR.width  = 12;
        vsbR.height = availR.height;
        vsbR.x = availR.x + availR.width - vsbR.width;
        vsbR.y = availR.y;

        if(viewport != null) {
          viewport.setBounds(availR);
        }
        if(vsb != null) {
          vsb.setVisible(true);
          vsb.setBounds(vsbR);
        }
      }
    });
    scrollPane.getVerticalScrollBar().setUI(new BasicScrollBarUI() {
      private final Dimension d = new Dimension();
      @Override protected JButton createDecreaseButton(int orientation) {
        return new JButton() {
          @Override public Dimension getPreferredSize() {
            return d;
          }
        };
      }
      @Override protected JButton createIncreaseButton(int orientation) {
        return new JButton() {
          @Override public Dimension getPreferredSize() {
            return d;
          }
        };
      }
      @Override
      protected void paintTrack(Graphics g, JComponent c, Rectangle r) {}
      @Override
      protected void paintThumb(Graphics g, JComponent c, Rectangle r) {
        Graphics2D g2 = (Graphics2D)g.create();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
        Color color = null;
        JScrollBar sb = (JScrollBar)c;
        if(!sb.isEnabled() || r.width>r.height) {
          return;
        }else if(isDragging) {
          color = new Color(200,200,100,200);
        }else if(isThumbRollover()) {
          color = new Color(255,255,100,200);
        }else {
          color = new Color(220,220,200,200);
        }
        g2.setPaint(color);
        g2.fillRoundRect(r.x,r.y,r.width,r.height,10,10);
        g2.setPaint(Color.WHITE);
        g2.drawRoundRect(r.x,r.y,r.width,r.height,10,10);
        g2.dispose();
      }
      @Override
      protected void setThumbBounds(int x, int y, int width, int height) {
        super.setThumbBounds(x, y, width, height);
        scrollbar.repaint();
      }
    });
    return scrollPane;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new TranslucentScrollBarTest().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}
Apparel answered 4/5, 2013 at 15:17 Comment(1)
Sadly the proposed solution will break JTable and won't display the table header.Flashing
L
3

Here is an improved version I did for a private project. It also supports horizontal scrollbar.

Code:

import javax.swing.*;
import javax.swing.plaf.basic.BasicScrollBarUI;

import java.awt.*;

/**
* This is an implementation of a JScrollPane with a modern UI
* 
* @author Philipp Danner
*
*/
public class ModernScrollPane extends JScrollPane {

    private static final long serialVersionUID = 8607734981506765935L;

    private static final int SCROLL_BAR_ALPHA_ROLLOVER = 100;
    private static final int SCROLL_BAR_ALPHA = 50;
    private static final int THUMB_SIZE = 8;
    private static final int SB_SIZE = 10;
    private static final Color THUMB_COLOR = Color.Black;

    public ModernScrollPane(Component view) {
        this(view, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
    }

    public ModernScrollPane(int vsbPolicy, int hsbPolicy) {
        this(null, vsbPolicy, hsbPolicy);
    }

    public ModernScrollPane(Component view, int vsbPolicy, int hsbPolicy) {

        setBorder(null);

        // Set ScrollBar UI
        JScrollBar verticalScrollBar = getVerticalScrollBar();
        verticalScrollBar.setOpaque(false);
        verticalScrollBar.setUI(new ModernScrollBarUI(this));

        JScrollBar horizontalScrollBar = getHorizontalScrollBar();
        horizontalScrollBar.setOpaque(false);
        horizontalScrollBar.setUI(new ModernScrollBarUI(this));

        setLayout(new ScrollPaneLayout() {
            private static final long serialVersionUID = 5740408979909014146L;

            @Override
            public void layoutContainer(Container parent) {
                Rectangle availR = ((JScrollPane) parent).getBounds();
                availR.x = availR.y = 0;

                // viewport
                Insets insets = parent.getInsets();
                availR.x = insets.left;
                availR.y = insets.top;
                availR.width -= insets.left + insets.right;
                availR.height -= insets.top + insets.bottom;
                if (viewport != null) {
                    viewport.setBounds(availR);
                }

                boolean vsbNeeded = isVerticalScrollBarfNecessary();
                boolean hsbNeeded = isHorizontalScrollBarNecessary();

                // vertical scroll bar
                Rectangle vsbR = new Rectangle();
                vsbR.width = SB_SIZE;
                vsbR.height = availR.height - (hsbNeeded ? vsbR.width : 0);
                vsbR.x = availR.x + availR.width - vsbR.width;
                vsbR.y = availR.y;
                if (vsb != null) {
                    vsb.setBounds(vsbR);
                }

                // horizontal scroll bar
                Rectangle hsbR = new Rectangle();
                hsbR.height = SB_SIZE;
                hsbR.width = availR.width - (vsbNeeded ? hsbR.height : 0);
                hsbR.x = availR.x;
                hsbR.y = availR.y + availR.height - hsbR.height;
                if (hsb != null) {
                    hsb.setBounds(hsbR);
                }
            }
        });

        // Layering
        setComponentZOrder(getVerticalScrollBar(), 0);
        setComponentZOrder(getHorizontalScrollBar(), 1);
        setComponentZOrder(getViewport(), 2);

        viewport.setView(view);
    }
    private boolean isVerticalScrollBarfNecessary() {
        Rectangle viewRect = viewport.getViewRect();
        Dimension viewSize = viewport.getViewSize();
        return viewSize.getHeight() > viewRect.getHeight();
    }

    private boolean isHorizontalScrollBarNecessary() {
        Rectangle viewRect = viewport.getViewRect();
        Dimension viewSize = viewport.getViewSize();
        return viewSize.getWidth() > viewRect.getWidth();
    }

    /**
     * Class extending the BasicScrollBarUI and overrides all necessary methods
     */
    private static class ModernScrollBarUI extends BasicScrollBarUI {

        private JScrollPane sp;

        public ModernScrollBarUI(ModernScrollPane sp) {
            this.sp = sp;
        }

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

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

        @Override
        protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) {
        }

        @Override
        protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) {
            int alpha = isThumbRollover() ? SCROLL_BAR_ALPHA_ROLLOVER : SCROLL_BAR_ALPHA;
            int orientation = scrollbar.getOrientation();
            int x = thumbBounds.x;
            int y = thumbBounds.y;

            int width = orientation == JScrollBar.VERTICAL ? THUMB_SIZE : thumbBounds.width;
            width = Math.max(width, THUMB_SIZE);

            int height = orientation == JScrollBar.VERTICAL ? thumbBounds.height : THUMB_SIZE;
            height = Math.max(height, THUMB_SIZE);

            Graphics2D graphics2D = (Graphics2D) g.create();
            graphics2D.setColor(new Color(THUMB_COLOR.getRed(), THUMB_COLOR.getGreen(), THUMB_COLOR.getBlue(), alpha));
            graphics2D.fillRect(x, y, width, height);
            graphics2D.dispose();
        }

        @Override
        protected void setThumbBounds(int x, int y, int width, int height) {
            super.setThumbBounds(x, y, width, height);
            sp.repaint();
        }

        /**
         * Invisible Buttons, to hide scroll bar buttons
         */
        private static class InvisibleScrollBarButton extends JButton {

            private static final long serialVersionUID = 1552427919226628689L;

            private InvisibleScrollBarButton() {
                setOpaque(false);
                setFocusable(false);
                setFocusPainted(false);
                setBorderPainted(false);
                setBorder(BorderFactory.createEmptyBorder());
            }
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(400, 400));

        JPanel content = new JPanel();
        content.setBackground(Color.WHITE);
        content.setPreferredSize(new Dimension(500, 500));
        content.add(new JLabel("test"));
        frame.add(new ModernScrollPane(content));

        frame.pack();
        frame.setVisible(true);
    }
}
Liatrice answered 22/10, 2015 at 17:26 Comment(0)
S
1

Custom scrollbar preview :

Custom scrollbar code :

public class CustomScrollBarUI extends BasicScrollBarUI {
    
      private final Dimension d = new Dimension();

      @Override
      protected JButton createDecreaseButton(int orientation) {
        return new JButton() {
          
            private static final long serialVersionUID = -3592643796245558676L;

            @Override
              public Dimension getPreferredSize() {
                return d;
              }
            };
      }

      @Override
      protected JButton createIncreaseButton(int orientation) {
        return new JButton() {
          
            private static final long serialVersionUID = 1L;

        @Override
          public Dimension getPreferredSize() {
            return d;
          }
        };
      }

      @Override
      protected void paintTrack(Graphics g, JComponent c, Rectangle r) {
      }

      @Override
      protected void paintThumb(Graphics g, JComponent c, Rectangle r) {
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        Color color = null;
        JScrollBar sb = (JScrollBar) c;
        if (!sb.isEnabled() || r.width > r.height) {
          return;
        } else if (isDragging) {
          color = Color.DARK_GRAY; // change color
        } else if (isThumbRollover()) {
          color = Color.LIGHT_GRAY; // change color
        } else {
          color = Color.GRAY; // change color
        }
        g2.setPaint(color);
        g2.fillRoundRect(r.x, r.y, r.width, r.height, 10, 10);
        g2.setPaint(Color.WHITE);
        g2.drawRoundRect(r.x, r.y, r.width, r.height, 10, 10);
        g2.dispose();
      }

      @Override
      protected void setThumbBounds(int x, int y, int width, int height) {
        super.setThumbBounds(x, y, width, height);
        scrollbar.repaint();
      }
    }

Then use it like this:

YOUR_COMPONENT.getVerticalScrollBar().setUI(new CustomScrollBarUI());
Strigose answered 7/12, 2018 at 3:11 Comment(0)
F
0

Sadly the proposed solutions will break JTable and won't display the table header, but I found this solution that seems to work.

Flashing answered 14/11, 2015 at 15:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.