Java更新小圈子

时间:2010-01-04 14:15:53

标签: java paint shape

我需要在表单上显示大量(500+)个小圆圈来模拟LED。但是,这些圆圈需要非常小,直径大约为8或9像素。

到目前为止,在我的测试中,我已经整理了一些代码,这些代码创建了一个使用Shape(Ellipse2D.Double)的Led类,并直接在JFrame的paint方法中显示它。

这让我有两个观察/问题:

1)首先,除非有替代方法,否则Java在绘制小圆圈时似乎有问题。它们似乎在右下角“打破”,笔宽为默认值(或1像素),这会使这部分切掉,留下变形的圆圈。如果有任何方法我可以绘制(很多)小圆圈并让它们看起来正确吗?

2)我的子类JFrame重写了paint方法来绘制这些'leds',尽管也调用super.paint来确保绘制JFrame。然而,我看到它很少在第一次出现时绘制LED,或者当窗体移出屏幕并返回时,或者当它放在前面并再次移开的应用程序时,以及绘制方法的唯一时间当我最小化/最大化表格时调用。每次表格需要绘画时都不应该调画吗?

4 个答案:

答案 0 :(得分:3)

你不应该覆盖paint()。请改用paintComponent()。此外,JFrames有些奇怪,我会使用JPanel作为我的BaseClass。

关于你的观察:这可能是由抗锯齿引起的吗?您是否尝试通过setRenderingHints()来关闭抗锯齿?

编辑:在下面的评论之后,我写了一个小测试程序。圈子看起来很不错:

import javax.swing.*;
import java.awt.Graphics2D;
import java.awt.Graphics;
import java.awt.Dimension;
import java.awt.RenderingHints;

class Test extends JFrame {

    public Test() {
        setContentPane(new JPanel() {
                public void paintComponent(Graphics g){
                    super.paintComponent(g);
                    Graphics2D g2d = (Graphics2D) g;
                    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    for (int i = 0; i < 500; i++){
                        int x = (int) (Math.random() * getWidth());
                    int y = (int) (Math.random() * getHeight());
                    g.fillOval(x,y,8,8);
                    }
                }
        });
    }

    public static void main(String[] args){
        Test t = new Test();
        t.setSize(new Dimension(640, 480));
        t.setVisible(true);
    }
}

答案 1 :(得分:2)

我一直在讨论这个问题一段时间,结果与这里描述的结果类似,当我最终得知fillOval()比drawOval()做得更好的事实。或Ellipse2D。以下略显苛刻的方法让我得到了我所需要的东西:

g2d.setColor(Color.black);                    
g2d.fillOval((int)x, (int)(y - w / 2), (int)w, (int)w);
g2d.setColor(Color.white);           
g2d.fillOval((int)x+1, (int)(y - w / 2)+1, (int)w-2, (int)w-2);

答案 2 :(得分:1)

这些LED应该是与表单上其他所有内容相同的组件。我认为您应该使用图标,可能ImageIcon来表示您的LED。这样,您基本上可以将它们渲染一次,然后在需要时显示相同的图像。您可以使用图像,因为这样您就可以使用具有您想要看到的形状的图像。

答案 3 :(得分:1)

就'break'而言,我会看一下你的图形对象的斜角设置。

但是,我建议在程序启动时读取.png,然后显示它而不是自己绘制。


RE:paint()没有一直被调用。

是的,这就是它的工作原理。如果您需要在特定时间重新绘制组件,则需要强制它。调用repaint()强制重绘。

如果你打算从另一个线程(即一个计时器线程)调用repaint(),请确保将调用包装在SwingUtilities.invokeLater()中:

SwingUtilities.invokeLater( new Runnable()
{
    @Override
    public void run()
    {
        myForm.repaint();
    }
} );

更新:也许你应该发布一些代码......我把一个小测试应用程序放在一起,并没有看到小圆圈的任何问题。

public class MyPanel extends JPanel
{
    public void paint(Graphics _g)
    {
        Graphics2D g = (Graphics2D) _g;

        g.setStroke( new BasicStroke(1f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND) );
        for(int x = 10, w = 1; w < 20; x += w*2, w++)
        {
            Ellipse2D.Double ed = new Ellipse2D.Double(x, 10, w, w);
            g.fill( ed );
        }

        for(int x = 10, w = 1; w < 20; x += w*2, w++)
        {
            Ellipse2D.Double ed = new Ellipse2D.Double(x, 80, w, w);
            g.draw( ed );
        }
    }

    public static void main(String[] args)
    {
        JFrame frame = new JFrame();
        frame.add( new MyPanel() );
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.setSize( 400, 400 );

        frame.setVisible( true );
    }
}

我尝试改变中风参数,看看我是否可以造成视力中断但是不成功。你看到了什么?


不要击败死马,但当我放大该程序的输出时,我的圆圈几乎是对称的,减去左边的一个小像素:

circle pics

这与你得到的相似吗?