绘制多个圆圈的问题(drawOval / Java)

时间:2015-01-12 13:11:56

标签: java graphics paintcomponent

我的问题如下:我的实际项目(下面的代码是简化版本)涉及许多同心圆(每个都有不同的颜色)和利用Timer的动画。使用 drawOval 方法绘制圆圈。

我的问题是,当绘制这些同心圆时,这些圆的轮廓中似乎存在大量的间隙,我猜这与圆由像素和线组成的事实有关。是任何形状,所以圆的外观是一种幻觉。我这样说是因为当我为 drawRect 交换 drawOval 方法时,这幅画看起来就像你期望的那样。

当搞乱其他人的代码时,我看到使用RenderingHints以某种方式解决了这个问题,但是动画速度超出了我觉得可以接受的程度。

下面是绘制内容的屏幕截图。我们没有看到一个坚固的不透明圆圈(因为在这个例子中绘制的所有圆圈都具有相同的颜色),我们看到了:

what we actually see

这是我的简化代码:

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 ,并使用更高的笔画值,我仍然发现我有某些人工制品出现的问题类似于Pavel发布的截图。这是我运行动画的完整应用程序的截图,如果你仔细观察,你会发现大多数给定圆圈的颜色不一致,导致这些奇怪的结果。它们的分布实际上遵循与上面发布的屏幕截图相同的模式,因此这些选项无法解决基本问题。这是我的屏幕截图: my full application in action

7 个答案:

答案 0 :(得分:2)

画出完美的圆圈是不可能的。

尝试使用以下方法

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,它减慢了你的动画,但你没有给我们任何动画代码,所以也许尝试我的代码(看看动画实现会很好)。它看起来更好,但仍然不是你想要的。将笔划设置为另一个值将解决此问题(设置为至少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更改为其他值)。

enter image description here

答案 1 :(得分:1)

您可能希望Stroke更大。在类似于你的情况下我已经幸运了

答案 2 :(得分:0)

您可以尝试在Circle函数中添加此行:draw函数:

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);

答案 3 :(得分:0)

这是因为计算机无法画出完美的圆圈。

计算机使用方形像素来逼近实际圆圈但是它不可能达到完美并且导致某些像素无法显示

绘制一个圆圈可以帮助你

a detailed explanation

答案 4 :(得分:0)

请你试试fillOval方法而不是drawOval。

g.fillOval(topLeft, topLeft, diameter, diameter);

enter image description here

答案 5 :(得分:0)

扭转你的想法。从最外面的圆开始,然后绘制内圆等,以最小的圆圈结束。您应该在此过程中使用fillOval

答案 6 :(得分:0)

通常对圆圈/椭圆形有用的其他渲染提示是

g.setRenderingHint( RenderingHints.  KEY_STROKE_CONTROL,
                    RenderingHints.VALUE_STROKE_PURE);

查看我的other answer with more details and example