【发布时间】:2014-11-05 22:35:25
【问题描述】:
我有很多JLabel,希望它们的拐角处平滑。我怎样才能做到这一点?我已经在 SO 上搜索过,但没有找到任何答案。
有人可以帮我提供一个简单而准确的代码来为JLabel's 制作圆角吗?
其他问题是询问一些额外的细节,如边框等,但我只想要精确和最简单的代码来为JLabel's 制作圆角。
【问题讨论】:
标签: java swing graphics jlabel rounded-corners
我有很多JLabel,希望它们的拐角处平滑。我怎样才能做到这一点?我已经在 SO 上搜索过,但没有找到任何答案。
有人可以帮我提供一个简单而准确的代码来为JLabel's 制作圆角吗?
其他问题是询问一些额外的细节,如边框等,但我只想要精确和最简单的代码来为JLabel's 制作圆角。
【问题讨论】:
标签: java swing graphics jlabel rounded-corners
说真的,最简单的解决方案是在 JLabel 周围画一个 RoundRectangle2D...
现在,您可以在标签的 paintComponent 或 paintBorder 方法中执行此操作,但是当您可以制作自己的边框以可重复使用的方式完成工作时,您为什么还要打扰,例如...
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.AbstractBorder;
public class TestRoundedBorder {
public static void main(String[] args) {
new TestRoundedBorder();
}
public TestRoundedBorder() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBackground(Color.RED);
setLayout(new GridBagLayout());
JLabel label = new JLabel("Test");
label.setBorder(new RoundedBorder(Color.BLACK, 20));
add(label);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public class RoundedBorder extends AbstractBorder {
private final Color color;
private final int gap;
public RoundedBorder(Color c, int g) {
color = c;
gap = g;
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(color);
g2d.draw(new RoundRectangle2D.Double(x, y, width - 1, height - 1, gap, gap));
g2d.dispose();
}
@Override
public Insets getBorderInsets(Component c) {
return (getBorderInsets(c, new Insets(gap, gap, gap, gap)));
}
@Override
public Insets getBorderInsets(Component c, Insets insets) {
insets.left = insets.top = insets.right = insets.bottom = gap / 2;
return insets;
}
@Override
public boolean isBorderOpaque() {
return false;
}
}
}
现在,如果您想要“平滑”边缘,您将不得不将 RenderingHints 提供给 Graphics 上下文,例如...
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2d = (Graphics2D) g.create();
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);
g2d.setColor(color);
g2d.draw(new RoundRectangle2D.Double(x + 1, y + 1, width - 2, height - 2, gap, gap));
g2d.dispose();
}
【讨论】:
您不能在实际的JLabel 区域上进行圆角;它们总是矩形的。但是,一个简单的替代方法是将JLabel 的ImageIcon 设置为具有圆边且不使用边框的图像。设置ImageIcon:
yourLabel.setIcon(new ImageIcon(getClass().getResource("/path/to/your/image.png"));
// Note: Relative path, starts from root of project
您的图像应该具有JLabel 的尺寸。
请注意,如果找不到图像,这将抛出NullPointerException。确保你走对了路!
创建一个ImageIcon,将其大小调整为JLabel:
ImageIcon ico = new ImageIcon("/path/to/your/image.png");
Image img = ico.getImage();
BufferedImage bi = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics g = bi.createGraphics();
g.drawImage(img, 0, 0, yourLabel.getWidth(), yourLabel.getHeight(), null);
IconImage newIco = new IconImage(bi);
yourLabel.setIcon(newIco);
编辑:
这是使用Graphics2D 制作圆角边框的最佳方法。
首先,创建一个名为 RoundedBorder 的新类。将此代码粘贴到其中:
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.geom.Line2D;
import javax.swing.border.AbstractBorder;
public class RoundedBorder extends AbstractBorder {
public RoundedBorder(Color c, int g) {
color = c;
gap = g;
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
super.paintBorder(c, g, x, y, width, height);
Graphics2D g2d;
if (g instanceof Graphics2D) {
g2d = (Graphics2D) g;
g2d.setColor(color);
System.out.println(x + y);
g2d.draw(new Line2D.Double((double)x, (double)y + 10, (double)x + 3, (double)y + 3));
g2d.draw(new Line2D.Double((double)x + 3, (double)y + 3, (double)x + 10, (double)y));
g2d.draw(new Line2D.Double((double)x + 10, (double)y, (double)x + 30, (double)y));
g2d.draw(new Line2D.Double((double)x + 30, (double)y, (double)x + 33, (double)y + 2));
g2d.draw(new Line2D.Double((double)x + 33, (double)y + 2, (double)x + 36, (double)y + 8));
g2d.draw(new Line2D.Double((double)x + 36, (double)y + 8, (double)x + 36, (double)y + 28));
g2d.draw(new Line2D.Double((double)x + 36, (double)y + 28, (double)x + 34, (double)y + 31));
g2d.draw(new Line2D.Double((double)x + 34, (double)y + 31, (double)x + 32, (double)y + 33));
g2d.draw(new Line2D.Double((double)x + 32, (double)y + 33, (double)x + 6, (double)y + 33));
g2d.draw(new Line2D.Double((double)x + 6, (double)y + 33, (double)x + 3, (double)y + 31));
g2d.draw(new Line2D.Double((double)x + 3, (double)y + 31, (double)x, (double)y + 27));
g2d.draw(new Line2D.Double((double)x, (double)y + 27, (double)x, (double)y + 10));
}
}
@Override
public Insets getBorderInsets(Component c) {
return (getBorderInsets(c, new Insets(gap, gap, gap, gap)));
}
@Override
public Insets getBorderInsets(Component c, Insets insets) {
insets.left = insets.top = insets.right = insets.bottom = gap;
return insets;
}
@Override
public boolean isBorderOpaque() {
return true;
}
// Variable declarations
private final Color color;
private final int gap;
}
然后,在您的 JFrame 类中,将此设置为 JLabel 的边框,请执行以下操作:
yourLabel.setBorder(new RoundedBorder(Color.black, 10));
正如 MadProgrammer 所提到的,比画线更有效的方法是使用RoundRectangle2D。要使用它,请将所有 draw 行替换为
g2d.draw(new RoundRectangle2D.Double(x, y, width - 1, height - 1, gap, gap));
随意修改边框。这是使用Graphics2D的语法:
g2d.draw(new Line2D.Double((double)x1, (double)y1, (double)x2, (double)y2));
或
g2d.draw(new Line2D.Double(Point2D p1, Point2D p2));
我希望这会有所帮助!
【讨论】:
simplest 是使用 LineBorder 类。
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class RoundedLineBorder extends JPanel {
public RoundedLineBorder() {
super(true);
JLabel label = new JLabel("<html>Stack<br/>Overflow</html>");
LineBorder line = new LineBorder(Color.blue, 1, true); // color, thickness, rounded
label.setBorder(line);
add(label, BorderLayout.CENTER);
}
public static void main(String s[]) {
JFrame frame = new JFrame("Rounded Line Border");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 200);
frame.setContentPane(new RoundedLineBorder());
frame.setVisible(true);
}
}
但结果并不是城里最好看的圆角;-)
【讨论】: