如何使用ArrayList将随机形状绘制到我的框架中?

时间:2019-05-26 19:30:17

标签: java swing

我很想学习如何完成这个项目。我想以随机的颜色和位置绘制三个随机形状,并将它们添加到列表中(稍后需要在第二个窗口中播放)。

这是我所拥有的:

 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());
            }
        }
    }
    */


 }

修改后,Frame类现在看起来像这样。我是Java新手,对此错误感到抱歉

1 个答案:

答案 0 :(得分:0)

首先,花一些时间阅读multiple jframes is good or bad practice。之后,请阅读how to use Swing Timers,以了解如何使它每秒绘制一个新形状(我不确定是否要使用此功能,但看起来确实如此)。如果在Swing应用程序中使用Thread.sleep()方法,则由于线程处于休眠状态,因此整个GUI将冻结,并且事件将无法发生。

您提供给我们的代码不是Short, Self Contained, Correct (Compilable), Example,因为我们必须对其进行编辑才能使其运行。因此,我创建了一个示例,以向您展示我在实践中的意思。不要忘记在代码内注释注释

代码:

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

预览:

Image preview