如何设计带圆角的 JButton?

How do I design a JButton with round corners?

我正在尝试设计一个 JButton。

我希望 JButton 看起来像这样:

我尝试使用 Polygon 来实现这一点,但我无法像上面看到的那样使角变圆。

我设计的是这样的:

生成此按钮的代码如下:

public class arcButton extends JButton{

public arcButton() {
    Dimension size = getPreferredSize();
    size.width = size.height = Math.max(size.width, size.height);
    setPreferredSize(size);
    setContentAreaFilled(false);
}
protected void paintComponent(Graphics g) {
    
    
    if (getModel().isArmed()) {
        g.setColor(Color.CYAN.darker().darker());
    } else {
        g.setColor(Color.CYAN.darker());
    }
    int xPoints[] = {getWidth(), getWidth()/3, getWidth()/3, getWidth()*3/4, getWidth()*3/4, getWidth(), getWidth()*3/4, getWidth()*3/4, 0, 0, getWidth()};
    int yPoints[] = {getHeight()*7/9, getHeight()*7/9, getHeight()*3/9, getHeight()*3/9, getHeight()*4/9, getHeight()*2/9, 0, getHeight()/9, getHeight()/9, getHeight(), getHeight()};      
    g.fillPolygon(xPoints, yPoints, xPoints.length);
    super.paintComponent(g);
}

protected void paintBorder(Graphics g) {
    g.setColor(Color.cyan);
    int xPoints[] = {getWidth(), getWidth()/3, getWidth()/3, getWidth()*3/4, getWidth()*3/4, getWidth(), getWidth()*3/4, getWidth()*3/4, 0, 0, getWidth()};
    int yPoints[] = {getHeight()*7/9, getHeight()*7/9, getHeight()*3/9, getHeight()*3/9, getHeight()*4/9, getHeight()*2/9, 0, getHeight()/9, getHeight()/9, getHeight(), getHeight()};      
    g.drawPolygon(xPoints, yPoints, xPoints.length);
}
Polygon polygon;

public boolean contains(int x, int y) {
    if (polygon == null ||
            !polygon.getBounds().equals(getBounds())) {
        int xPoints[] = {getWidth(), getWidth()/3, getWidth()/3, getWidth()*3/4, getWidth()*3/4, getWidth(), getWidth()*3/4, getWidth()*3/4, 0, 0, getWidth()};
        int yPoints[] = {getHeight()*7/9, getHeight()*7/9, getHeight()*3/9, getHeight()*3/9, getHeight()*4/9, getHeight()*2/9, 0, getHeight()/9, getHeight()/9, getHeight(), getHeight()};          
        polygon = new Polygon(xPoints,yPoints,xPoints.length);
    }
    return polygon.contains(x, y);
}
}

我尝试用圆弧绘制,但是当我在 paintComponent 中使用 ((Graphics2D)g).draw(arc) 时。鼠标在GUI上一直报错

我该如何处理?

我创建了以下 GUI。

我没有扩展 JButton,而是创建了一个 class 来容纳两个 BufferedImages。一个代表箭头,一个代表按下的按钮。

我创建了一个测试 GUI,这样我就可以一次绘制一小段箭头。我最终创建了两个 Polygons,一个用于半圆,一个用于箭头。

这是完整的可运行代码。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class CustonButtonGUI implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new CustonButtonGUI());
    }
    
    private ButtonImages buttonImages;
    
    public CustonButtonGUI() {
        this.buttonImages = new ButtonImages();
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Custom JButton");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.add(createMainPanel(), BorderLayout.CENTER);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private JPanel createMainPanel() {
        JPanel panel = new JPanel(new FlowLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(100, 100, 100, 100));
        
        BufferedImage image = buttonImages.getMainImage();
        
        JButton button = new JButton();
        button.setPreferredSize(new Dimension(image.getWidth(panel), 
                image.getHeight(panel)));
        button.setIcon(new ImageIcon(image));
        button.setPressedIcon(new ImageIcon(buttonImages.getPressedImage()));
        panel.add(button);
        
        return panel;
    }
    
    private class ButtonImages {
        
        private final BufferedImage mainImage;
        private final BufferedImage pressedImage;
        
        public ButtonImages() {
            this.mainImage = createMainImage(120, 200);
            this.pressedImage = createPressedImage(120, 200);
        }
        
        private BufferedImage createMainImage(int width, int height) {
            BufferedImage image = new BufferedImage(width, height, 
                    BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = (Graphics2D) image.getGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, width, height);
            
            g2d.setColor(Color.BLACK);
            g2d.fillPolygon(createArrowPolygon(width, height));
            g2d.fillPolygon(createCircularPolygon(width, height));
            
            g2d.dispose();
            return image;
        }
        
        private Polygon createArrowPolygon(int width, int height) {
            Polygon polygon = new Polygon();
            
            int margin = 10;
            int arrowWidth = 30;
            int x = width - margin;
            int y = height - margin;
            
            polygon.addPoint(x, y - arrowWidth);
            polygon.addPoint(x - arrowWidth, y - arrowWidth - arrowWidth);
            polygon.addPoint(x - arrowWidth, y);
            
            return polygon;
        }
        
        private Polygon createCircularPolygon(int width, int height) {
            Polygon polygon = new Polygon();
            
            int centerY = height / 2;
            int margin = 10;
            Point centerPoint = new Point(width - margin - 30, centerY);
            double radius = centerY - 55.0;
            
            for (int angle = 90; angle <= 270; angle++) {
                double theta = Math.toRadians(angle);
                int x = (int) Math.round(Math.cos(theta) * radius) + centerPoint.x;
                int y = (int) Math.round(Math.sin(theta) * radius) + centerPoint.y;
                polygon.addPoint(x, y);
            }
            
            radius += 25.0;
            for (int angle = 270; angle >= 90; angle--) {
                double theta = Math.toRadians(angle);
                int x = (int) Math.round(Math.cos(theta) * radius) + centerPoint.x;
                int y = (int) Math.round(Math.sin(theta) * radius) + centerPoint.y;
                polygon.addPoint(x, y);
            }
            
            return polygon;
        }
        
        private BufferedImage createPressedImage(int width, int height) {
            BufferedImage image = new BufferedImage(width, height, 
                    BufferedImage.TYPE_INT_RGB);
            return image;
        }
        
        public BufferedImage getMainImage() {
            return mainImage;
        }
        
        public BufferedImage getPressedImage() {
            return pressedImage;
        }
            
    }

}