Java Graphics.fillPolygon:如何渲染右边和底边?

绘制多边形时,Java2D会留下右边和底边。 我明白为什么这样做了。 但是,我想绘制一些包含这些边缘的东西。 我fillPolygon一件事是跟随具有相同坐标的fillPolygon ,但这似乎留下了空白。 (见底部的小三角形图像。)有两种可能性,但我不清楚哪一种。 要启用抗锯齿,我这样做:

 renderHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); renderHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2d.setRenderingHints(renderHints); 

一种可能性是在α通道上没有进行抗锯齿处理,因此间隙是由于过度绘制引起的。 在这种情况下,如果alpha通道是抗锯齿的,那么边缘将正确邻接。 另一种可能性是这里只有一个差距。

我怎样才能解决这个问题?

另外,我不确定,但看起来多边形轮廓实际上可能太大了。 也就是说,它可能比我想要包括的右边和下边更远。

谢谢。

在此处输入图像描述

– 更新 –

基于Hovercraft Full of Eels的一个非常好的建议,我做了一个可编辑的例子:

 import java.awt.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JOptionPane; public class polygon { private static final int WIDTH = 20; public static void main(String[] args) { BufferedImage img = new BufferedImage(WIDTH, WIDTH, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); int[] xPoints = {WIDTH / 3, (2*WIDTH) / 3, WIDTH / 3}; int[] yPoints = {0, WIDTH / 2, WIDTH}; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setColor(Color.green); g2.drawLine(0, WIDTH-1, WIDTH, WIDTH-1); g2.drawLine(0, 0, WIDTH, 0); g2.drawLine(WIDTH/3, 0, WIDTH/3, WIDTH); g2.drawLine((2*WIDTH/3), 0, (2*WIDTH/3), WIDTH); g2.setColor(Color.black); g2.drawPolygon(xPoints, yPoints, xPoints.length); g2.setColor(Color.black); g2.fillPolygon(xPoints, yPoints, xPoints.length); g2.dispose(); ImageIcon icon = new ImageIcon(img); JLabel label = new JLabel(icon); JOptionPane.showMessageDialog(null, label); } } 

如果将填充的多边形保留为红色,则会得到下面的图像(缩放500%),这表示多边形不会一直延伸到右边缘。 也就是说,垂直绿线对应于x=(2*WIDTH)/2 ,尽管红色多边形包括该坐标,但它不会在那里绘制任何像素。

在此处输入图像描述

为了查看间隙问题,我将程序中的red变为black 。 在此图像中,您可以在右下方看到一个微妙的间隙,其中fillPolygon绘制的轮廓与fillPolygon绘制的轮廓不完全fillPolygon

在此处输入图像描述

在简单的可编辑可运行程序中向我们展示您的绘图代码。 例如,当我尝试模仿您的图像并使用RenderingHints时,它似乎会生成具有完整右/下边缘的合适大小的图像:

 import java.awt.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; public class Foo002 { private static final int WIDTH = 20; public static void main(String[] args) { BufferedImage img = new BufferedImage(WIDTH, WIDTH, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); int[] xPoints = { WIDTH / 3, (2 * WIDTH) / 3, WIDTH / 3 }; int[] yPoints = { 0, WIDTH / 2, WIDTH }; g2.setColor(Color.black); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2.fillPolygon(xPoints, yPoints, xPoints.length); g2.dispose(); ImageIcon icon = new ImageIcon(img); JLabel label = new JLabel(icon); label.setBorder(BorderFactory.createLineBorder(Color.black)); JPanel panel = new JPanel(); panel.add(label); JOptionPane.showMessageDialog(null, panel); } } 

如果您可以向我们展示类似的程序来重现您的问题,那么我们可以为您提供更好的帮助。

我喜欢@HFOE所示的ImageIcon的便利性,但这种变化可能会让你更容易看到发生了什么。 从Graphics API,

绘制图形轮廓的操作通过遍历像素之间的无限细路径来操作,像素大小的笔垂直向下并且在路径上的锚点的右侧。 填充图形的操作通过填充无限细路径的内部来操作。

相比之下, Graphics2D必须遵循更复杂的抗锯齿规则,这允许它“在线外绘制”。

PixelView

 import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridLayout; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import javax.swing.JFrame; import javax.swing.JPanel; /** @see http://stackoverflow.com/questions/7701097 */ public class PixelView extends JPanel { private static final int SIZE = 20; private static final int SCALE = 16; private BufferedImage img; public PixelView(Color fill) { this.setBackground(Color.white); this.setPreferredSize(new Dimension(SCALE * SIZE, SCALE * SIZE)); img = new BufferedImage(SIZE, SIZE, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); int[] xPoints = {SIZE / 3, (2 * SIZE) / 3, SIZE / 3}; int[] yPoints = {0, SIZE / 2, SIZE}; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setColor(Color.green); g2.drawLine(0, SIZE - 1, SIZE, SIZE - 1); g2.drawLine(0, 0, SIZE, 0); g2.drawLine(SIZE / 3, 0, SIZE / 3, SIZE); g2.drawLine((2 * SIZE / 3), 0, (2 * SIZE / 3), SIZE); g2.setColor(Color.black); g2.drawPolygon(xPoints, yPoints, xPoints.length); g2.setColor(fill); g2.fillPolygon(xPoints, yPoints, xPoints.length); g2.dispose(); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(img, 0, 0, getWidth(), getHeight(), null); } private static void display() { JFrame f = new JFrame("PixelView"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setLayout(new GridLayout(1, 0)); f.add(new PixelView(Color.black)); f.add(new PixelView(Color.red)); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { display(); } }); } }