绘制多个圆的问题(drawOval / Java)
Posted
技术标签:
【中文标题】绘制多个圆的问题(drawOval / Java)【英文标题】:Issues with drawing multiple circles (drawOval / Java) 【发布时间】:2015-03-10 06:24:02 【问题描述】:我的问题如下:我的实际项目(下面的代码是其简化版本)涉及许多同心圆(每个都有不同的颜色)和使用计时器的动画。圆圈是使用 drawOval 方法绘制的。
我的问题是,当绘制这些同心圆时,这些圆的轮廓中似乎有很多间隙,我猜这与圆由像素和线条组成的事实有关是任何形状,所以圆形的外观是一种错觉。我这样说是因为当我将 drawOval 方法换成 drawRect 时,绘画看起来就像你所期望的那样。
在弄乱其他人的代码时,我发现使用 RenderingHints 以某种方式解决了这个问题,但是将动画减慢到了我认为可以接受的程度。
下面是绘制的截图。我们看到的是:
这是我的简化代码:
Test10
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class Test10 extends JPanel
Circle[] circles;
public static void main(String[] args)
new Test10().go();
void go()
JFrame frame = new JFrame("Circle Test");
frame.getContentPane().add(this);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
circles = new Circle[200];
for (int i = 0; i < 200; i++)
circles[i] = new Circle(i, ((2 * ( 200 - i) + 1)));
repaint();
frame.setPreferredSize(new Dimension(500,500));
frame.pack();
frame.setVisible(true);
public void paintComponent(Graphics g)
for (Circle circle : circles )
circle.draw(g);
圈子
import java.awt.Graphics;
public class Circle
int topLeft;
int diameter;
public Circle(int topLeft, int diameter)
this.topLeft = topLeft;
this.diameter = diameter;
void draw(Graphics g)
g.drawOval(topLeft, topLeft, diameter, diameter);
谁能向我解释a)为什么会发生这种情况,b)如何克服这个问题。更新 尝试了各种方法,包括从最外圈开始并使用 fillOval 而不是 drawOval,以及使用更高的 stroke 值,我仍然发现我有某些人工制品出现的问题与 Pavel 发布的屏幕截图相似。这是我运行动画的完整应用程序的屏幕截图,如果您仔细观察,您会发现大多数给定圆圈的颜色不一致,从而导致这些奇怪的结果。它们的分布实际上遵循与上面发布的屏幕截图相同的模式,因此这些选项显然没有解决一些基本问题。这是我的屏幕截图:
【问题讨论】:
画一个实心圆或两个同心圆不就行了吗? 查看我的帖子顶部,在完整的应用程序中,每个圆圈都有不同的颜色,创建了一系列漂亮的同心圆。这就是我不使用fillOval的原因,无论如何谢谢:P 您是否正在实施 Futurama 的催眠蟾蜍? ;-) 【参考方案1】:画完美的圆是不可能的。
试试下面的方法
public void paintComponent(Graphics g)
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(2));
int i = 0;
for (Circle circle : circles )
Shape circle2 = new Ellipse2D.Double(i++, i, circle.diameter, circle.diameter);
g2d.draw(circle2);
您说您尝试使用RenderingHints
,它会减慢您的动画速度,但您没有给我们任何动画代码,所以也许试试我的代码(很高兴看到动画实现)。它看起来更好,但仍然不是你想要的。将 stroke 设置为另一个值将解决此问题(至少设置为 2)。另一种是使用.fill()
而不是.draw()
。我知道它并不完美,但你可以试试。
另一个想法
我想,也许你可以给你的图像添加一些模糊,这样那些伪影就看不见了? 我以前没有做过,但我发现了这个(found HERE):
private class BlurGlass extends JComponent
private JFrame f;
public BlurGlass(JFrame f)
this.f = f;
setOpaque(false);
setFocusable(false);
public void paintComponent(Graphics g)
int w = f.getWidth();
int h = f.getHeight();
setLocation(0, 0);
setSize(w, h);
g.setColor(new Color(0, 0, 0, 0.3f));
g.fillRect(0, 0, w, h);
现在在 go()
方法中的某处:
frame.setGlassPane(new BlurGlass(frame));
frame.getGlassPane().setVisible(true);
对我来说看起来好多了。玩一下这个 GlassPane 颜色(尝试将 .3f 更改为其他值)。
【讨论】:
感谢您的所有建议,我已经尝试了所有建议,但我仍然得到奇怪的人工制品,因为在个别圈子中不能始终保持其确切的颜色,特别是在 NE NW SW 和 SE 方向。如果您有任何其他想法,请告诉我。 新信息看起来不错,稍后再试,谢谢!【参考方案2】:您可能想让Stroke 更大。在与您类似的情况下,我很幸运
【讨论】:
谢谢 稍后会玩这个,看起来很有希望。 试一试,对我的原始帖子进行了更新,以显示由于它们不理想而产生的结果。这种方法当然有帮助,但它仍然存在问题。感谢您的帮助,如果您能查看更新将不胜感激:)【参考方案3】:您可以尝试在绘图函数中的 Circle 类中添加此行:
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
//and draw the Oval on g2
另一种解决方案可能是填充圆圈:
Ellipse2D.Double circle = new Ellipse2D.Double(x, y, diameter, diameter);
g2.fill(circle);
【讨论】:
感谢您的帮助,有关问题仍然存在的原因的详细信息,请参阅更新。非常好的建议,尽管我需要熟悉渲染提示。更多帮助将不胜感激。 另一种方法是使用一些预定义的同心圆图像并逐渐显示图像。太糟糕了,它不是一个程序化解决方案,它可能会为您提供更好的图形。 嗯,完整的应用程序是一个动画,其中每一帧都包含一系列同心圆,RGB 分量以指定的增量上升。随着每一帧的进行,圆圈将它们的颜色传递到它们外部的圆圈上,从而产生虫洞的效果。有点需要编程对吗? 我有一个最终的想法。尝试应用模糊滤镜,看看它是否看起来更好一些。 java2s.com/Code/Java/2D-Graphics-GUI/ImageEffectSharpenblur.htm【参考方案4】:这是因为计算机无法画出完美的圆。
计算机使用方形像素来近似真实的圆形,但它不可能达到完美,导致某些像素不显示
画一个实心圆会帮助你
a detailed explanation
【讨论】:
正如我所怀疑的,非常感谢。我的问题尚未解决,如果您仍然有兴趣提供帮助,我已在我的问题中添加了详细信息,非常感谢该链接,稍后会好好阅读!【参考方案5】:请您尝试使用 fillOval 方法而不是 drawOval。
g.fillOval(topLeft, topLeft, diameter, diameter);
【讨论】:
在我的身上比在你的身上效果更好。我在你的丝网印刷品上看到的那些对称的人工制品是不可取的。感谢您的回答,尽管到目前为止似乎是最有用的。 是的,我也得到了那些文物,有什么线索可以摆脱它们吗?【参考方案6】:扭转你的想法。从最外圈开始,然后画内圈,以此类推,以最小的圆圈结束。你应该在这个过程中使用fillOval
。
【讨论】:
嗨,谢谢,我实际上已经尝试过这种方法,虽然它在涉及多种颜色时适用于小规模,但它会产生有趣的人工制品。我编辑了我的问题,将此信息与另一个屏幕截图一起包含在内。再次感谢 这是因为填充椭圆填充了圆圈,并且圆圈的半径之间存在很大差异。如果您想绘制一个带有粗边框的空圆(以获得一个完美的圆),那么您可以在您的 fillOval 内绘制具有几乎相同半径的 drawOval。 感谢您的回复。圆的半径之间的差异很大?相邻圆的半径相差 1,所以我不太确定我明白你的意思...... 哦,我错过了。不过,试试我改进后的想法,它可能会有所帮助。【参考方案7】:另一个通常对圆形/椭圆有用的渲染提示是
g.setRenderingHint( RenderingHints. KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_PURE);
见我的other answer with more details and example。
【讨论】:
以上是关于绘制多个圆的问题(drawOval / Java)的主要内容,如果未能解决你的问题,请参考以下文章