JButton式样的修改,包括按钮的正常状态、鼠标悬停状态以及按下状态,且不使用背景图片修改,依靠paint()渲染。
相关代码:
public class MyButton extends JButton {
private float alpha = 1f; // 底色的透明度,默认为不透明
private int isMouseEntered = 1;// 鼠标是否进入按钮
public MyButton() {
initStyle();
}
public MyButton(String buttonText) {
super(buttonText);
initStyle();
//添加鼠标监听
addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
//当鼠标进入时,鼠标进入状态改为TRUE,并重绘按钮
isMouseEntered = 0;
repaint();
super.mouseEntered(e);
}
@Override
public void mouseExited(MouseEvent e) {
isMouseEntered = 1;
repaint();
}
@Override
public void mousePressed(MouseEvent arg0) {
isMouseEntered = 2;
repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
isMouseEntered = 0;
repaint();
}
});
}
/**
* 初始化按钮样式
*/
private void initStyle() {
//初始化透明按钮
setOpaque(false);
setBorder(null);
// setBorderPainted(false);
setFocusable(false);
setBackground(null);
// setFocusPainted(false);
setContentAreaFilled(false);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// 绘制渐变底色
switch(isMouseEntered) {
case 0:
AlphaComposite composite = AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, alpha);
g2.setComposite(composite);
drawButtonBackground(g2, this, Color.decode("#E0F1FC"), Color.decode("#DEEBFE"),
Color.decode("#D6E5F5"), Color.decode("#FFFFFF"));
break;
case 1:
break;
case 2:
AlphaComposite composite1 = AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, alpha);
g2.setComposite(composite1);
// drawButtonBackground(g2, this, Color.decode("#D6E5F5"), Color.decode("#FFFFFF"),
// Color.decode("#FFFFFF"), Color.decode("#D6E5F5"));
drawButtonPressBackground(g2, this, Color.decode("#D6E5F5"), Color.decode("#EFF5FE"),
Color.decode("#EFF5FE"), Color.decode("#D6E5F5"));
default:
break;
}
super.paintComponent(g);
}
private static void drawButtonBackground(Graphics2D g2, JToggleButton bt,
Color c1, Color c2, Color c3, Color c4) {
// 使平滑
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// 造一个圆角区域
RoundRectangle2D.Float r2d = new RoundRectangle2D.Float(0, 0,
bt.getWidth() - 1, bt.getHeight() - 1, 10, 10);
Shape clip = g2.getClip();
g2.clip(r2d);
g2.setClip(clip);
g2.setColor(Color.decode("#afafaf"));
g2.drawRoundRect(0, 0, bt.getWidth() - 2, bt.getHeight() - 1, 10, 10);
// 渐变背景
g2.setPaint(new GradientPaint(2, 2, c1, 1, bt.getHeight() / 3, c2));
g2.fillRoundRect(2, 2, bt.getWidth() - 5, bt.getHeight() / 3, 10, 10);
// 渐变二段
g2.setPaint(new GradientPaint(1, bt.getHeight() / 3, c3, 1, bt
.getHeight(), c4));
g2.fillRoundRect(2, bt.getHeight() / 3, bt.getWidth() - 5,
bt.getHeight() / 3 * 2 - 1, 10, 10);
// g2.dispose();
}
private static void drawButtonPressBackground(Graphics2D g2, JToggleButton bt,
Color c1, Color c2, Color c3, Color c4) {
// 使平滑
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// 造一个圆角区域
RoundRectangle2D.Float r2d = new RoundRectangle2D.Float(0, 0,
bt.getWidth() - 1, bt.getHeight() - 1, 10, 10);
Shape clip = g2.getClip();
g2.clip(r2d);
g2.setClip(clip);
// 外边框
g2.drawRoundRect(0, 0, bt.getWidth() - 2, bt.getHeight() - 1, 10, 10);
// 渐变背景
g2.setPaint(new GradientPaint(1, bt.getHeight()/7, c1, 1, bt.getHeight() / 3, c2));
g2.fillRect(2, 2, bt.getWidth() - 5, bt.getHeight() / 3);
// 渐变二段
g2.setPaint(new GradientPaint(1, bt.getHeight() / 3, c3, 1, bt
.getHeight(), c4));
g2.fillRect(2, bt.getHeight() / 3, bt.getWidth() - 5,
bt.getHeight() / 3 * 2 - 1);
// 内边框
g2.setColor(Color.decode("#afafaf"));
g2.drawRoundRect(1, 1, bt.getWidth() - 3, bt.getHeight() - 2, 9, 9);
g2.drawRoundRect(2, 2, bt.getWidth() - 4, bt.getHeight() - 3, 8, 8);
g2.setColor(Color.decode("#cfcfcf"));
g2.drawRoundRect(2, 3, bt.getWidth() - 4, bt.getHeight() - 4, 8, 7);
}
}
注意代码中的几个部分:
1、首先是paintComponent方法中最后一行,我们调用了父类的paintComponent方法,这是因为我们要靠父类来绘制字符,但是父类的这个方法除了绘制字符之外还会绘制其他的,所以我们需要关闭掉其他的(当然我们也可以自己来绘制字符,但是JButton提供了方法为什么不用呢)
2、我们在构造方法那里调用了:
setBorderPainted(false);
setFocusPainted(false);
setContentAreaFilled(false);
告诉父类不用绘制边框,不用绘制焦点,不用绘制内容部分,这部分我们自己来搞。
3、使平滑:
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)告诉绘制API我们需要平滑一点,否则绘制出来会有很多锯齿。
4、透明度:
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,tran))告诉绘图API我们需要绘制一个有透明度的,tran就是透明度(0-1)。
5、边框的边角变直角为圆角,我们绘制一个RoundRectangle2D,这个就是边角都为圆角的方形,然后我们根据这个方形来clip我们的方形,这样方形就被RoundRectangle2D的圆角方形包裹,从而变成了圆角方形。
6、最后就是绘制外边线和内边线,通过改变内边线和外边线的色变从而造成陷入或者突出效果, 在此句之前加setColor可改变当前画笔颜色:
g2.drawRoundRect(1, 1, bt.getWidth() - 3, bt.getHeight() - 2, 9, 9);