Drawing 2 Balls to move in different direction on Java but one disappeared [closed]

浪子不回头ぞ 提交于 2019-11-29 13:06:26

Problems...

  1. while-loop in the Event Dispatching Thread which adjusts the positions of graphics objects
  2. Thread.sleep in paint methods.
  3. Not calling super.paintComponent
  4. Updating the state of an object in the paintComponent method.

Swing uses a single thread model that is responsible for, amongst other things, dispatching repaint requests to all the components.

Performing any operation in the EDT that stops from processing these events, will prevent Swing from repainting the UI. This will make it look like your animation has suddenly gone from the start to the end in a single step.

Take a look at Concurrency in Swing for more details. In particular, take a look at Initial Threads and How to use Swing Timers

I should highlight point 4-

You do not control the repaint cycle. Repaint requests may be raised for a number of reasons, that you didn't ask for, these will cause your objects to be updated beyond your control or when you don't want them to be. You should never change the state of any part of your UI from within any paint method.

Simple Example

This is a very simple example, but it demonstrates the basic concepts you need to understand in order to do any animation in Swing

public class SimpleBouncyBall {

    public static void main(String[] args) {
        new SimpleBouncyBall();
    }

    public SimpleBouncyBall() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new CourtPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class CourtPane extends JPanel {

        private Ball ball;
        private int speed = 5;

        public CourtPane() {
            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Rectangle bounds = new Rectangle(new Point(0, 0), getSize());
                    if (ball == null) {
                        ball = new Ball(bounds);
                    }
                    speed = ball.move(speed, bounds);
                    repaint();
                }
            });
            timer.setRepeats(true);
            timer.setCoalesce(true);
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(100, 100);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g); 
            if (ball != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                Point p = ball.getPoint();
                g2d.translate(p.x, p.y);
                ball.paint(g2d);
                g2d.dispose();
            }
        }

    }

    public class Ball {

        private Point p;
        private int radius = 12;

        public Ball(Rectangle bounds) {

            p = new Point();
            p.x = 0;
            p.y = bounds.y + (bounds.height - radius) / 2;

        }

        public Point getPoint() {
            return p;
        }

        public int move(int speed, Rectangle bounds) {

            p.x += speed;
            if (p.x + radius >= (bounds.x + bounds.width)) {

                speed *= -1;
                p.x = ((bounds.x + bounds.width) - radius) + speed;

            } else if (p.x <= bounds.x) {

                speed *= -1;
                p.x = bounds.x + speed;

            }

            p.y = bounds.y + (bounds.height - radius) / 2;

            return speed;

        }

        public void paint(Graphics2D g) {
            g.setColor(Color.RED);
            g.fillOval(0, 0, radius, radius);
        }

    }

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!