Java Swing JButton自定义Icon圆角显示异常及适配问题
问题2:圆角显示效果不一致的原因&修复方法
原因主要有3点:
- 你调用
fillRoundRect时传入的宽高参数为组件的完整宽高c.getWidth()、c.getHeight(),而Java Swing的绘制坐标系从0开始计数,有效绘制区域的x坐标范围是0 ~ 宽度-1,y坐标范围是0 ~ 高度-1,你绘制到了超出区域的位置,超出部分会被截断,就会出现右下角等边角变成直角的问题。 - 你没有开启Graphics的抗锯齿渲染,圆角边缘会出现明显的像素锯齿,放大后看起来圆角效果不对。
- 当前
EmptyIcon的getIconWidth、getIconHeight方法返回值为0,不符合Icon接口的规范,会导致按钮的布局计算出现异常,也会间接影响绘制效果。
修复方法:
- 绘制
fillRoundRect时,宽高参数改为getWidth()-1、getHeight()-1 - 把Graphics强制转为Graphics2D,开启抗锯齿渲染配置
- 修正
EmptyIcon的宽高返回逻辑,构造时传入固定宽高,或者根据绑定的组件尺寸动态返回。
问题1:自定义Icon适配按钮尺寸的简便方案
有两个更简单的实现思路:
方案1:优化现有EmptyIcon实现
修改EmptyIcon的代码,支持自动适配父组件尺寸,同时修复绘制问题,修改后的代码如下:
import java.awt.Graphics2D; import java.awt.RenderingHints; public final static class EmptyIcon implements Icon { private final Color color; private final int arcWidth; private final int arcHeight; public EmptyIcon(Color color) { this(color, 5, 5); } public EmptyIcon(Color color, int arcWidth, int arcHeight) { this.color = color; this.arcWidth = arcWidth; this.arcHeight = arcHeight; } @Override public void paintIcon(Component c, Graphics g, int x, int y) { if (c == null || color == null) return; Graphics2D g2d = (Graphics2D) g.create(); // 开启抗锯齿 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setColor(color); // 宽高减1避免超出绘制区域,同时使用传入的x、y作为绘制起点,符合Icon接口规范 g2d.fillRoundRect(x, y, c.getWidth()-1, c.getHeight()-1, arcWidth, arcHeight); g2d.dispose(); } @Override public int getIconWidth() { // 适配你当前按钮的宽度,也可以在构造时传入动态值 return 340; } @Override public int getIconHeight() { // 适配你当前按钮的高度,也可以在构造时传入动态值 return 27; } }
方案2:直接重写JButton的paintComponent方法
如果你只是要实现圆角背景的按钮,不需要单独做Icon,直接自定义JButton子类重写绘制逻辑更简单,不需要额外处理Icon和按钮的适配问题:
import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.RenderingHints; // 初始化按钮时直接重写绘制逻辑 JButton b2 = new JButton("Big Button") { @Override protected void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D) g.create(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 绘制圆角背景 g2d.setColor(Color.RED); g2d.fillRoundRect(0, 0, getWidth()-1, getHeight()-1, 5, 5); // 绘制按钮文字 g2d.setColor(getForeground()); FontMetrics fm = g2d.getFontMetrics(); int textX = (getWidth() - fm.stringWidth(getText())) / 2; int textY = (getHeight() + fm.getAscent() - fm.getDescent()) / 2; g2d.drawString(getText(), textX, textY); g2d.dispose(); } }; // 去掉按钮默认背景和边框 b2.setContentAreaFilled(false); b2.setBorderPainted(false);
内容的提问来源于stack exchange,提问作者Unhandled Exception
相关产品推荐
相关产品推荐

