问题
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:
Thanks for every help.
回答1:
I guess you are looking for a transparent scrollbar.
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);
}
}
回答2:
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);
}
}
回答3:
Sadly the proposed solutions will break JTable and won't display the table header, but I found this solution that seems to work.
回答4:
Custom scrollbar preview
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:
YOUR_COMPONENT.getVerticalScrollBar().setUI(new CustomScrollBarUI());
来源:https://stackoverflow.com/questions/16373459/java-jscrollbar-design