在 JButton 中添加装饰

Add decorations in JButton

我目前在 JavaSwing 进行 GUI 开发。 我正在尝试使用 JButton 创建一个类似于 HTML 代码的 button,它已添加到 getContentPane(),但我不知道该怎么做并且我不知所措。


当前代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Main {
  public static void main(String[] args) {

    JFrame frame = new JFrame();
    frame.setTitle("TITLE");
    frame.setVisible(true);
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(1000, 800);
    frame.getContentPane().setLayout(new FlowLayout());

    JButton button = new JButton("Click Here");
    frame.getContentPane().add(button);
    button.setBackground(Color.RED);
    button.setForeground(Color.WHITE);
    button.setOpaque(true);
    button.setPreferredSize(new Dimension(150, 50));

    }

  }

我试图创建的实体有点难以口头解释,所以我尝试使用 HTML 重现我试图创建的内容。如下:


HTML 代码:

<div class="btn">Click Here</div>

<style>
.btn {
  background-color: red;
  display: inline-block;
  height: 70px;
  width: 150px;
  text-align: center;
  color: white;
  padding-top: 35px;
  font-size: 25px;
  border-radius: 50px;
  box-shadow: 0px 5px #b70d0b;
  opacity: 0.7;
  cursor: pointer;
}
  .btn:hover {
    opacity: 1;
  }
  .btn:active{
    position: relative;
    top: 5px;
    box-shadow: none;
  }
</style>

这是执行时的样子:下图是我在JavaSwing中的理想。

这次的问题是:

我不确定这样问是不是太多了。我很清楚问题太多了,所以如果你能只回答我能回答的问题,我将不胜感激。

同时,我自己Google研究了这个问题,但none符合我的理想,所以我在这里问。


至于我做了什么,我是这样做的:

我看了here,但是当我输入小数点时,比如setOpacity(0.5),我得到一个错误setOpacity(double) is undefined

我提到了边界半径 here,但是当我 运行 它时没有任何反应。可能是我的文风或版本有问题。我觉得是我写的方式有问题,或者版本有问题,但是没找到原因。

我尝试复制 MouseEvent 用于悬停 here,但版本可能不同,或者出现错误。

那么,我应该编写什么代码来实现我的要求? 如果你能帮助我,我将不胜感激。

谢谢。

没有“简单”的方法可以做到这一点,您要么必须创建自己的自定义按钮(从 JButton 扩展),要么必须创建自己的 UI 委托 class(这可能是首选方向,但它很复杂)

Why not use a Border

因为 Border 无法填充...如果填充,它将覆盖按钮的文本

您应该先查看 Painting in AWT and Swing, Performing Custom Painting and 2D Graphics 以更好地了解解决方案的工作原理。

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {
        public TestPane() {
            setBorder(new EmptyBorder(32, 32, 32, 32));
            setLayout(new GridBagLayout());
            FancyButton btn = new FancyButton();
            btn.setText("Click me");
            add(btn);
        }
    }

    public class FancyButton extends JButton {

        private int cornerRadius = 32;
        private BufferedImage backgroundImage;

        private float alpha = 0.25f;

        public FancyButton() {
            setBackground(Color.RED);
            setForeground(Color.WHITE);
            // This is important
            setBorderPainted(false);
            // This is important
            setContentAreaFilled(false);
            // This is important
            int padding = cornerRadius / 2;
            setBorder(new EmptyBorder(padding, padding, padding, padding));
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseEntered(MouseEvent e) {
                    alpha = 1;
                    repaint();
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    alpha = 0.25f;
                    repaint();
                }
            });
            addComponentListener(new ComponentAdapter() {
                @Override
                public void componentResized(ComponentEvent e) {
                    backgroundImage = null;
                }
            });
        }

        @Override
        public boolean isOpaque() {
            return false;
        }

        @Override
        public Insets getInsets() {
            Insets insets = super.getInsets(); 
            insets.bottom += 5;
            return insets;
        }

        @Override
        public Insets getInsets(Insets insets) {
            super.getInsets(insets);
            insets.bottom += 5;
            return insets;
        }

        @Override
        protected void paintComponent(Graphics g) {
            if (backgroundImage == null) {
                backgroundImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
                Graphics2D g2d = backgroundImage.createGraphics();
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setColor(getBackground().darker());
                g2d.fillRoundRect(0, 5, getWidth(), getHeight() - 5, cornerRadius, cornerRadius);
                g2d.setColor(getBackground());
                g2d.fillRoundRect(0, 0, getWidth(), getHeight() - 5, cornerRadius, cornerRadius);
                g2d.dispose();
            }

            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setComposite(AlphaComposite.SrcOver.derive(alpha));
            g2d.drawImage(backgroundImage, 0, 0, this);
            super.paintComponent(g2d);
            g2d.dispose();
        }
    }
}