-2

I am keen to learn how I can finish this project. I want to draw three random shapes in random colors and positions and add them to the list (which later need to be played in the second window).

Here is what I have:

 public
    class Frame extends JFrame { // here was implements Runnable when i 
                                 // used Thread

    public  ArrayList<MyShape> shapesList = new ArrayList<MyShape>(30); // create list
    public  JPanel shapePanel;
    public  Timer timer;
    public  final int  NEW_SHAPE_FREQUENCY = 1000;
    public  Rectangle myRect;
    public  Oval myOval;
    public  Line myLine;

 public Frame() {

    super("I do not need title, just 50%");
    setSize(800, 600);
    setDefaultCloseOperation(3);
    setLocationRelativeTo(null);
    setVisible(true);
    setLayout(new BorderLayout());

    shapePanel = new JPanel() {
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (MyShape s : shapesList) {
            g.setColor(myOval.color);  // in this line i have 
                                       // Exception: NullPointerException
                g.fillRect(((int)(getWidth()*Math.random()*0.8d)),((int) 
 (getHeight()*Math.random()*0.8d)), (int) (myRect.x2),(int) myRect.y2); 
            }
        }
    };

    add(shapePanel);
    initTimer();

    // Thread t0 = new Thread(this);  // How can i use Threads in this case ??
    // t0.start();

 }

 private void initTimer() {
    timer = new Timer(NEW_SHAPE_FREQUENCY, e -> {
        shapesList.add(new MyShape()); // Add a new shape to the arraylist
        shapePanel.repaint(); // Repaint the panel, so the new shape is 
                              // visible
    });
    timer.start();
  }
  /*
    @Override
    public void run() {

        while (true) {
            try {

                Random rand = new Random();
                switch (rand.nextInt(3)+1) {
                    case 1:
                        shapesList.add((Shape)myRect);
                        break;

                    case 2:
                        shapesList.add((Shape)myOval);
                        break;

                    case 3:
                        shapesList.add((Shape)myLine);
                        break;
                }

                repaint();
                Thread.sleep(1000);

            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
    }
    */


 }

After modification, the Frame class now looks like this. I am newbie with coding in Java sorry about this errors

1 Answers1

0

First of all, take some time and read if multiple jframes is good or bad practice. After that, read how to use Swing Timers, in order to learn how you will make it paint a new shape every second (i am not sure if you want this feature, but it seems so). If you use Thread.sleep() method in a Swing application, the whole GUI will freeze since the thread is sleeping and events will not be able to take place.

The code you gave to us is not an Short, Self Contained, Correct (Compilable), Example since we will have to edit it in order to make it run. For that reason I've created an example in order to show you what i mean in practice. Do not forget to note the comments inside the code.

Code:

public class RandomShape extends JFrame {
    private static final long serialVersionUID = 6617760910198114903L;
    private static final int NEW_SHAPE_FREQUENCY = 1000; // every second new shape
    private List<Shape> shapes = new ArrayList<>(); // Keep the shapes
    private JPanel shapePanel;
    private Timer timer; //A javax.swing.Timer

    public RandomShape() {
        super("Random shapes");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new BorderLayout()); // set border layout to the content pane
        shapePanel = new JPanel() {
            /*
             * Override paint component in order to add custom painting to this panel. But
             * of course, start by calling super.paintComponent()
             */
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                for (Shape s : shapes) {
                    g.setColor(s.color);
                    g.fillRect(s.x, s.y, s.width, s.height);
                }
            }
        };
        // Add it to the center of the border layout in order to take all window space
        add(shapePanel, BorderLayout.CENTER);
        setSize(400, 400);
        setLocationRelativeTo(null);
        initTimer();
    }

    private void initTimer() {
        timer = new Timer(NEW_SHAPE_FREQUENCY, e -> {
            shapes.add(new Shape()); // Add a new shape to the arraylist
            shapePanel.repaint(); // Repaint the panel, so the new shape is visible
        });
        timer.start();
    }

    private static class Shape {
        private int x, y, height, width;
        private Color color;

        private Shape() {
            x = random(300);
            y = random(300);
            height = random(50);
            width = random(50);
            color = new Color(random(255), random(255), random(255));

        }

        private static int random(int max) {
            return (int) (Math.random() * max);
        }
    }

    public static void main(String[] args) {
        // Start application in its own thread, called Event Dispatch Thread.
        // For more info, read
        // https://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
        SwingUtilities.invokeLater(() -> new RandomShape().setVisible(true));
    }
}

Preview:

Image preview

George Z.
  • 6,643
  • 4
  • 27
  • 47
  • I modified the code a bit. I have a requirement to put threads in all this. The example you provided does not describe it in the threads, can I ask for an example with threads? – Mateusz Michalski May 26 '19 at 21:24