JButton 式样自定义

本文介绍了如何通过paint()方法在JButton上实现自定义样式,包括调整按钮的正常状态、鼠标悬停状态及按下状态的渐变背景颜色和透明度。通过设置透明度参数alpha,利用GradientPaint绘制不同渐变效果,同时运用AlphaComposite调整绘制顺序,最终达到美观且个性化的按钮外观。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值