要做到这个效果,可以重写BasicButtonUI然后给调用JButton的setUI,也可以继承JButton重写部分方法。两者原理都一样,我 这里用的是第二种。原理就是重新绘制Jbutton包括按钮,边框等,也就是重写paintComponent(Graphics g).
public class BasicButton extends JButton { /** * */ private static final long serialVersionUID = 1L; public static final Color BUTTON_COLOR1 = new Color(125, 161, 237); public static final Color BUTTON_COLOR2 = new Color(91, 118, 173); public static final Color BUTTON_BAK_COLOR1_1 = new Color(108, 135, 210, 179); public static final Color BUTTON_BAK_COLOR1_2 = new Color(108, 135, 210, 255); public static final Color BUTTON_BAK_COLOR2_1 = new Color(180, 230, 250, 179); public static final Color BUTTON_BAK_COLOR2_2 = new Color(180, 230, 250, 255); public static final Color BUTTON_FOREGROUND_COLOR = Color.BLACK; private boolean hover; public BasicButton(String text) { super(text); //步骤1 setBorderPainted(false); setFocusPainted(false); setContentAreaFilled(false); setForeground(BUTTON_FOREGROUND_COLOR); addMouseListener(new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { hover = true; repaint(); } @Override public void mouseExited(MouseEvent e) { hover = false; repaint(); } }); } @Override protected void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D) g.create(); int h = getHeight(); int w = getWidth(); // Color color2 = BUTTON_BAK_COLOR1_2; // Color color1 = BUTTON_BAK_COLOR2_2; float tran = 1F; if (!hover) { tran = 0.7F; // color2 = BUTTON_BAK_COLOR1_1; // color1 = BUTTON_BAK_COLOR2_1; } //步骤2 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); GradientPaint p1; GradientPaint p2; if (getModel().isPressed()) { p1 = new GradientPaint(0, 0, new Color(0, 0, 0), 0, h - 1, new Color(100, 100, 100)); p2 = new GradientPaint(0, 1, new Color(0, 0, 0, 50), 0, h - 3, new Color(255, 255, 255, 100)); } else { p1 = new GradientPaint(0, 0, new Color(100, 100, 100), 0, h - 1, new Color(0, 0, 0)); p2 = new GradientPaint(0, 1, new Color(255, 255, 255, 100), 0, h - 3, new Color(0, 0, 0, 50)); } //设置透明度 g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, tran)); Shape clip = g2d.getClip(); //绘制整个按钮 RoundRectangle2D.Float r2d = new RoundRectangle2D.Float(0, 0, w - 1, h - 1, h, h); g2d.clip(r2d); GradientPaint gp = new GradientPaint(0.0F, 0.0F, BUTTON_COLOR1, 0.0F, h, BUTTON_COLOR2, true); g2d.setPaint(gp); g2d.fillRect(0, 0, w, h); //鼠标移入就绘制立体效果 if (hover) { RoundRectangle2D.Float r2d2 = new RoundRectangle2D.Float(5, 2, w - 10, h / 2 - 1, h / 2, h / 2); g2d.clip(r2d2); GradientPaint gp2 = new GradientPaint(0.0F, 0.0F, BUTTON_BAK_COLOR2_2, 0.0F, h / 2, BUTTON_BAK_COLOR1_2, true); g2d.setPaint(gp2); g2d.fillRect(5, 2, w - 10, h / 2); } g2d.setClip(clip); //绘制边框 g2d.setPaint(p1); g2d.drawRoundRect(0, 0, w - 1, h - 1, h, h); g2d.setPaint(p2); g2d.drawRoundRect(1, 1, w - 3, h - 3, h - 2, h - 2); g2d.dispose(); super.paintComponent(g); } }
基本步骤就是:
1.先调用父类的方法,让父类不用绘制边框、不用绘制焦点、不用绘制内容,我们自己来完成这些东西。
2.调用抗锯齿的api,让我们paint出来的线条平滑,要不然会有相当难看的锯齿。
3.设置透明度。这个主要是为了做出鼠标移入、移出的效果。我这里是移入按钮,按钮颜色加深并且会有视觉效果上的“凸起”立体感;移出就颜色变浅,凸起感消失,恢复原样了。
4.绘制整个按钮。生成一个圆角矩形,并用由上到下的渐进色填充,这就是按钮的整体效果。
5.如果鼠标移入就绘制立体效果。在这里我是先生成一个高度为按钮一半的圆角矩形,然后从上到下用渐进色填充,最下面的颜色就是按钮本身在中间位置的颜色,这样看起来上面是白的,好像反光的立体效果。
6.绘制边框。用于点击效果的显示。
如果要真正想apple那样的效果,就还需要用另外的区域来模糊化下半个按钮部分,需要涉及到调整颜色之类的,我这就没做了,大概的效果图如下:
正常状态
鼠标移上去
鼠标按下去