Search code examples
javapaintshapes

Java Updating Small Circles


I need to display a large number (500+) of small circles on a form to simulate LEDs. However, these circles need to be quite small, around 8 or 9 pixels diameter.

So far, in my testing, I've put together some code that creates an Led class that uses a Shape (Ellipse2D.Double) and displays it directly on the JFrame from the JFrame's paint method.

This has led me to two observations/issues:

1) Firstly, unless there is an alternate method, Java appears to have trouble in drawing small circles. They appear to 'break' in the lower right corner with a pen width of default (or 1 pixel), which cuts this part off leaving a deformed circle. If there any way I can draw (lots of) small circles and have them look right?

2) My subclassed JFrame overrides the paint method to draw these 'leds', although calls the super.paint as well to ensure the JFrame gets drawn. However, I'm seeing that it rarely draws the led on the first appearance, or when the form is moved off-screen and back, or when an application it put in front and moved away again, and the only time the paint method is called is when I minimize/maximize the form. Shouldn't paint be called every time the form needs painting?


Solution

  • You shouldn't override paint(). Use paintComponent() instead. Also, JFrames are slightly strange things, I'd use JPanel as my BaseClass.

    About your observation: Might this be caused by antialiasing? Did you try to turn antialiasing off via setRenderingHints()?

    EDIT: After the comment below, I've written a small test program. Circles look nice with this:

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