我正在尝试制作一个自定义按钮(扩展
BasicButtonUI
),具有圆角。我发现我应该使用覆盖按钮方角的圆形边框。
我正在为我的按钮添加边框,如下所示:
b.setBorder(new RoundedBorder(20));
我是这样画边框的:
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Constants.windowColor);
g2d.setStroke(new BasicStroke(5f)); // Width of 5 pixels.
g2d.setPaintMode();
g2d.drawRoundRect(x, y, width-1, height-1, radius, radius);
}
但是,正如您在下面的屏幕截图中看到的那样,按钮的角向外“移动”了。它们甚至不与按钮的边缘对齐!
放大后是这样的:
截图上看起来不太像,但在现实生活中看起来很奇特!
我很困惑,为什么不修改您的自定义
BasicButtonUI
以绘制圆角区域,例如使用RoundRectangle2D
之类的东西。
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.LinearGradientPaint;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.basic.BasicButtonUI;
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() {
setLayout(new GridBagLayout());
setBackground(Color.RED);
setBorder(new EmptyBorder(23, 32, 32, 32));
JButton circleButton = new JButton("Hello");
circleButton.setUI(new CircleButtonUI());
circleButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("I've been triggered");
}
});
add(circleButton);
}
}
public class CircleButtonUI extends BasicButtonUI {
private Shape buttonShape;
@Override
public void installUI(JComponent c) {
super.installUI(c);
c.setOpaque(false);
// This is because on some platforms, the background
// is undefined or otherwise causes the button not
// to render
c.setBackground(Color.LIGHT_GRAY.brighter());
}
@Override
public boolean contains(JComponent c, int x, int y) {
if (buttonShape == null) {
return c.contains(x, y);
}
return buttonShape.contains(x, y);
}
@Override
public void paint(Graphics g, JComponent c) {
int width = c.getWidth() - 2;
int height = c.getHeight() - 2;
buttonShape = new RoundRectangle2D.Double(1, 1, width, height, 20, 20);
AbstractButton b = (AbstractButton) c;
paintContent(g, b);
super.paint(g, c);
}
protected void paintContent(Graphics g, AbstractButton b) {
if (buttonShape == null) {
return;
}
Graphics2D g2d = (Graphics2D) g.create();
// paint the interior of the button
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
ButtonModel model = b.getModel();
Color highlight = b.getBackground();
if (model.isArmed() && model.isPressed()) {
highlight = highlight.darker();
}
Color darklight = highlight.darker();
LinearGradientPaint lgp = new LinearGradientPaint(
buttonShape.getBounds().getLocation(),
new Point((int) buttonShape.getBounds().getMaxX(), (int) buttonShape.getBounds().getMaxY()),
new float[]{0, 1f},
new Color[]{highlight, darklight});
g2d.setPaint(lgp);
g2d.fill(buttonShape);
// draw the perimeter of the button
g2d.setColor(b.getBackground().darker().darker().darker());
g2d.draw(buttonShape);
g2d.dispose();
}
@Override
protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) {
// Paint focus highlight, if you want to
}
public Dimension getMinimumSize(JComponent c) {
Dimension size = super.getMinimumSize(c);
return new Dimension(size.width + 8, size.height + 16);
}
public Dimension getPreferredSize(JComponent c) {
Dimension size = super.getPreferredSize(c);
return new Dimension(size.width + 8, size.height + 16);
}
public Dimension getMaximumSize(JComponent c) {
Dimension size = super.getPreferredSize(c);
return new Dimension(size.width + 8, size.height + 16);
}
}
}
请注意,这只是一个示例,您需要做更多的工作才能获得功能齐全的实现。