如何设计带有圆角的 JButton?

问题描述

我正在尝试设计一个 JButton。

我希望 JButton 看起来像这样:

enter image description here

我尝试使用 polygon 来实现此目的,但无法使角变圆,如上所示。

我设计的看起来像这样:

enter image description here

生成此按钮的代码如下:

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/4,getWidth(),getWidth()};
    int yPoints[] = {getHeight()*7/9,getHeight()*7/9,getHeight()*3/9,getHeight()*4/9,getHeight()*2/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(),getHeight()};      
    g.drawpolygon(xPoints,xPoints.length);
}
polygon polygon;

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

我尝试用弧线绘制,但是当我在paintComponent 中使用((Graphics2D)g).draw(arc) 时。当鼠标在 GUI 上时,它不断给出很多错误

我应该如何处理这个问题?

解决方法

我创建了以下 GUI。

Custom JButton

我没有扩展 JButton,而是创建了一个类来保存两个 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));
        
        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,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,BufferedImage.TYPE_INT_RGB);
            return image;
        }
        
        public BufferedImage getMainImage() {
            return mainImage;
        }
        
        public BufferedImage getPressedImage() {
            return pressedImage;
        }
            
    }

}