1

I'm begining with JFrame, I'm triying to make a StarField, for the moment I'm adding the Star JComponent to the Starfield JFrame:

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;

public class Star extends JComponent{
    public int x;
    public int y;
    private final Color color = Color.YELLOW;

    public Star(int x, int y) {
       this.x = x;
       this.y = y;
    }

    public void paintComponent(Graphics g) {
       g.setColor(color);
       g.fillOval(x, y, 8, 8);
    }   
}

and the StarField code:

import javax.swing.*;

public class StarField extends JFrame{
    public int size = 400;
    public  Star[] stars = new Star[50];

    public static void main(String[] args) {
        StarField field = new StarField();
        field.setVisible(true);
    }

    public StarField() {
        this.setSize(size, size);
        for (int i= 0; i< stars.length; i++) {
            int x = (int)(Math.random()*size);
            int y = (int)(Math.random()*size);
            stars[i] = new Star(x,y);
            this.add(stars[i]);
        }       
    }
}

The problem it's thar it only print one star, I think it is the last one, the coords are working like they are supposed to do it, so I think the mistake is in the JComponent or JFrame implementation, I'm self-learning, so maybe my code isn't the correct way for using swing.

Thank you, and sorry for my english, I'd tried to write it the best I know.

2
  • Better have a look at LayoutManager. If I remember correctly the default Layout is BorderLayout which allows a total of 5 components at 5 different spots. this.add(stars[i]); overwrites every component previously added as you can only have one component at the BorderLayout.CENTER (which is default and therefore will magically appended to your add call, so that it actually is this.add(stars[i], BorderLayout.CENTER);) Commented Apr 11, 2018 at 9:45
  • 1
    Suggestions for the OP to improve the custom component: 1) don't hardcode the color. Instead you can use the setForeground(...) method to set a color for the oval and then use getForeground() when doing the painting. Then each oval can be a different color. 2) Don't hardcode the size. Make this a parameter. Then each oval can be a different size. 3) implement the getPreferredSize() method. This would be based on the parameter suggested in 2. This is used by layout managers to determine the size of the component. Commented Apr 11, 2018 at 14:23

1 Answer 1

1

In your case you cannot use a layout manager, and need to reset it to null. See the my code below

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.WindowConstants;

public class StarField extends JFrame {
    public int size = 400;

    public Star[] stars = new Star[50];

    public static void main(String[] args) {
        StarField field = new StarField();
        field.setVisible(true);
    }

    public StarField() {
        this.setSize(size, size);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        // usually you should use a normal layout manager, but for your task we need null
        getContentPane().setLayout(null);
        for (int i = 0; i < stars.length; i++) {
            int x = (int) (Math.random() * size);
            int y = (int) (Math.random() * size);
            stars[i] = new Star(x, y);
            this.add(stars[i]);
        }
    }

    public class Star extends JComponent {

        private final Color color = Color.YELLOW;

        public Star(int x, int y) {
            // need to set the correct coordinates
            setBounds(x, y, 8, 8);
        }

        @Override
        public void paintComponent(Graphics g) {
            g.setColor(color);
            g.fillOval(0, 0, getWidth(), getHeight());
        }
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

(1+) for addressing the layout issue and improved painting code so that the painting is always done at (0, 0).
In your case you cannot use a layout manager - FYI. You could consider using the Drag Layout. It allows you to position components at a random location while still providing some layout functionality such as setting the size of a component and determining the preferred size of the panel, so it will still work in a scroll pane. This class would assume the getPreferredSize() has been implemented correctly as suggestion in my comment to the original question.
@camickr Thanks for the info. Probably I'll use it somewhere. And big thanks again for the WrapLayout ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.