为什么图形不显示?绘制方法尊重笔划属性吗?
我想创建一个带圆角的自定义边框。
代码 -
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.border.AbstractBorder;
class JRoundedCornerBorder extends AbstractBorder
{
private static final long serialVersionUID = 7644739936531926341L;
private static final int THICKNESS = 5;
JRoundedCornerBorder()
{
super();
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height)
{
Graphics2D g2 = (Graphics2D)g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if(c.hasFocus())
{
g2.setColor(Color.BLUE);
}
else
{
g2.setColor(Color.BLACK);
}
g2.setStroke(new BasicStroke(THICKNESS, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2.drawRect(x, y, width - 1, height - 1);
g2.dispose();
}
@Override
public Insets getBorderInsets(Component c)
{
return new Insets(THICKNESS, THICKNESS, THICKNESS, THICKNESS);
}
@Override
public Insets getBorderInsets(Component c, Insets insets)
{
insets.left = insets.top = insets.right = insets.bottom = THICKNESS;
return insets;
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
// Add button with custom border
final JButton button = new JButton("Hello");
button.setBorder(new JRoundedCornerBorder());
frame.add(button);
// Add button without custom border
frame.add(new JButton("Goodbye"));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
结果 -
如您所见、Graphics.drawRect
完全忽略BasicStroke.CAP_ROUND
和BasicStroke.JOIN_ROUND
属性。为什么?
I want to create a custom border with rounded corners.
Code -
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.border.AbstractBorder;
class JRoundedCornerBorder extends AbstractBorder
{
private static final long serialVersionUID = 7644739936531926341L;
private static final int THICKNESS = 5;
JRoundedCornerBorder()
{
super();
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height)
{
Graphics2D g2 = (Graphics2D)g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if(c.hasFocus())
{
g2.setColor(Color.BLUE);
}
else
{
g2.setColor(Color.BLACK);
}
g2.setStroke(new BasicStroke(THICKNESS, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2.drawRect(x, y, width - 1, height - 1);
g2.dispose();
}
@Override
public Insets getBorderInsets(Component c)
{
return new Insets(THICKNESS, THICKNESS, THICKNESS, THICKNESS);
}
@Override
public Insets getBorderInsets(Component c, Insets insets)
{
insets.left = insets.top = insets.right = insets.bottom = THICKNESS;
return insets;
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
// Add button with custom border
final JButton button = new JButton("Hello");
button.setBorder(new JRoundedCornerBorder());
frame.add(button);
// Add button without custom border
frame.add(new JButton("Goodbye"));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Result -
As you can see, Graphics.drawRect
completely ignores the BasicStroke.CAP_ROUND
and BasicStroke.JOIN_ROUND
attributes. Why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
正如学习 Java 2D,第 1 部分中所述:
关键词是“居中”。我相信,当使用粗笔画进行绘制时,Java2D 总是会沿着起始坐标和结束坐标的像素中心之间的假设的无限细线将线条的粗细居中。例如,当绘制一条 7 像素粗的垂直蓝线时,Java2D 在所绘制的假设线段的每一侧绘制 3 个像素。
在您的示例中,厚度为 5 像素。您需要偏移坐标才能将笔划完全绘制在图形剪辑内。通过移动 2 个像素(或
THICKNESS/2
),圆角变得可见:As explained at Learning Java 2D, Part 1:
The key word is "centered". I believe that it is always the case that when drawing with thick strokes, Java2D will center the thickness of the line along the hypothetical, infinitesimally-thin line between the centers of the pixels at the starting and ending coordinates. For example, when drawing a vertical blue line 7 pixels thick, Java2D paints 3 pixels on each side of the hypothetical line segment that is being drawn.
In your example, the thickness is 5 pixels. You need to offset the coordinates to draw the stroke completely within the graphics clip. By moving in 2 pixels (or
THICKNESS/2
), the rounded corners become visible:问题是偏移:您实际上切断了中间的边框,因此角落看起来不是圆角的。考虑到这一点(这里仅用于偏移,还需要调整宽度)
编辑
修复了马虎的像素计数:-)
the problem is the offset: you'r effectively cutting-off the border in the middle so the corners appear to be not rounded. Taking it into account (here only for the offset, need to adjust width as well)
Edit
fixed sloppy pixel counting :-)