我正在尝试使用
Graphics2D
剪裁我的 RoundRectangle2D.Double
画布,但剪裁非常参差不齐且不平滑。我有以下代码来消除锯齿:
Graphics2D g = (Graphics2D)graphics;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
我知道它有效,因为当我使用
RoundRectangle2D.Double
绘制 Graphics2D.fill()
时,平滑效果很好。如何使剪裁平滑?
注意:我知道这篇文章,但这与
JPanels
和图像有关,但我不处理其中任何一个。我只是想平滑地剪切绘图区域的一部分。
在此先感谢您的帮助。
Example.java
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import javax.swing.*;
public class Example extends JPanel {
public Example() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLocation(10, 10);
setPreferredSize(new Dimension(400, 400));
setBackground(Color.BLACK);
Container container = frame.getContentPane();
container.add(this);
frame.pack();
frame.setVisible(true);
}
public void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
Graphics2D g = (Graphics2D)graphics;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
RoundRectangle2D clippingArea = new RoundRectangle2D.Double(50, 50, getWidth() - 100, getHeight() -100, 40, 40);
g.setClip(clippingArea);
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.BLACK);
String s = "area for me to draw on where";
g.drawString(s, getWidth()/2 - g.getFontMetrics().stringWidth(s)/2, getHeight()/2 - g.getFontMetrics().getHeight());
s = "the roundrectangle should be anti-aliased";
g.drawString(s, getWidth()/2 - g.getFontMetrics().stringWidth(s)/2, getHeight()/2);
}
public static void main(String[] args) {
new Example();
}
}
所以,根据你的例子,“简单”的答案是作弊。
RoundRectangle2D clippingArea = new RoundRectangle2D.Double(50, 50, getWidth() - 100, getHeight() - 100, 40, 40);
// Make the clipping space rectangular
g.setClip(clippingArea.getBounds2D());
g.setColor(Color.WHITE);
g.fill(clippingArea);
g.setColor(Color.BLACK);
基本上所有这一切都使裁剪区域成为矩形,然后使用
RoundRectangle2D
形状填充它。
因为你的大部分问题都围绕边缘展开,这消除了核心问题,圆边。
您“可能”解决问题的方法有多种,使用中间
BufferedImage
s 是一种方法(因此您可以将内容限制在指定区域,但仍应用“软裁剪”),但对于这种情况,这将是最简单的解决方案
你提的问题有两种思路
第一个想法
使用 setClip() 方法设置剪辑,并使用 Graphics 类的方法在特定范围内绘制。 这也是你提出来的idea
第二个想法
创建一个具有 Graphics 类型的 graphicsObj 字段的 BufferedImage 对象。
为图形对象设置渲染提示,如下所示:
graphicsObj.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
使用 fillOval() 方法绘制一个椭圆。 然后,使用 setComposite() 方法,为 Graphics 对象设置一个 AlphaComponent 对象,如下所示:
AlphaComposite alphaComposite = AlphaComposite.getInstance(AlphaComposite.SRC_IN);
graphicsObj.setComposite(alphaComposite);
然后使用 drawImage 或任何其他方法绘制一些东西。 这个 BufferedImage 就是你想要的。 只是不要忘记在任何要绘制 BufferedImage 的地方使用以下渲染提示:
setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
例子:
public void paint(Graphics g) {
super.paint(g);
BufferedImage bufferedImage = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);
Graphics2D bg2 = bufferedImage.createGraphics();
bg2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
bg2.fillOval(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight());
AlphaComposite alphaComposite = AlphaComposite.getInstance(AlphaComposite.SRC_IN);
bg2.setComposite(alphaComposite);
Image img = null;
try {
img = ImageIO.read(new File("some-image.png"));
} catch (IOException e) {
e.printStackTrace();
}
if (img == null) {
// TODO something
} else {
bg2.drawImage(img, 0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(), null);
}
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.drawImage(bufferedImage, 0, 0, getWidth(), getHeight(), null);
}
}