Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
324 views
in Technique[技术] by (71.8m points)

java - why my code "Bouncing ball" doesn't work?

I'm trying to write a code a bout a bouncing ball, but i'm stuck in how to make the ball bounced. The code seems correct, no wrong messages from eclipse and yet the ball doesn't move. Any help/hint is appreciate.

Here's my code:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class BouncingBallTest extends JFrame {

    private JButton jbtStart = new JButton("Start");
    private JButton jbtStop = new JButton("Stop");
    private Ball canvas = new Ball();

    public BouncingBallTest() {
        JPanel panel = new JPanel(); // Use the panel to group buttons
        panel.add(jbtStart);
        panel.add(jbtStop);

        add(canvas, BorderLayout.CENTER); // Add canvas to centre
        add(panel, BorderLayout.SOUTH); // Add panel to south

        // register listener
        jbtStart.addActionListener(new StartBouncingBallTest());
        jbtStop.addActionListener(new StopBouncingBallTest());

    }

    // the main method
    public static void main(String[] args) {
        JFrame frame = new BouncingBallTest();
        frame.setTitle("Bouncing Ball Test");
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(470, 300);
        frame.setVisible(true);
    }

    class StartBouncingBallTest implements ActionListener { // inner class
        @Override
        public void actionPerformed(ActionEvent e) {
            canvas.StartBouncingBallTest();
        }
    }

    class StopBouncingBallTest implements ActionListener { // inner class
        @Override
        public void actionPerformed(ActionEvent e) {
            canvas.StopBouncingBallTest();
        }
    }

    class Ball extends JPanel {
        private int radius = 10;
        private int x;
        private int y;
        private int dx = 3;
        private int dy = 3;

        private Timer timer = new Timer(20, new TimerListener());

        public void StartBouncingBallTest() {
            if (x > 0 && y > 0) {
                x += dx;
                y += dy;
            }

            else if (x == 0) {
                x -= dx;
                y += dy;
            }

            else if (y + (2 * radius) > getHeight()) {
                x += dx;
                y -= dy;
            }

            else if (y == 0) {
                x += dx;
                y -= dy;
            }

            else if (x + (2 * radius) > getWidth()) {
                x -= dx;
                y += dy;
            }
            repaint();

            timer.start();

        }

        public void StopBouncingBallTest() {

            timer.stop();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.GREEN);
            g.fillOval(x, y, 2 * radius, 2 * radius);

        }
    }

    class TimerListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            repaint();
        }
    }

}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Basically, nothing is moving the ball.

Each time the Swing Timer ticks, all you do is repaint.

You need to move the movement logic to the actionPerformed method of the ActionListener registered to the Timer

More like...

public void StartBouncingBallTest() {
    timer.start();
}

//...

class TimerListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        if (x > 0 && y > 0) {
            x += dx;
            y += dy;
        }

        else if (x == 0) {
            x -= dx;
            y += dy;
        }

        else if (y + (2 * radius) > getHeight()) {
            x += dx;
            y -= dy;
        }

        else if (y == 0) {
            x += dx;
            y -= dy;
        }

        else if (x + (2 * radius) > getWidth()) {
            x -= dx;
            y += dy;
        }
        repaint();
    }
}

This way, each time the Timer ticks, you are making update the position of the ball accordingly...

Updated with working example

I made two changes. I made your TimerListener an inner class of Ball, which allows it to access the variable and methods of Ball and modified your movement logic so it works

Bounce

class Ball extends JPanel {

    private int radius = 10;
    private int x;
    private int y;
    private int dx = 3;
    private int dy = 3;

    private Timer timer = new Timer(20, new TimerListener());

    public void StartBouncingBallTest() {

        timer.start();

    }

    public void StopBouncingBallTest() {

        timer.stop();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.GREEN);
        g.fillOval(x, y, 2 * radius, 2 * radius);

    }

    class TimerListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {

            if (x < 0 || x + (2 * radius) > getWidth()) {
                dx *= -1;
            }
            if (y < 0 || y + (2 * radius) > getHeight()) {
                dy *= -1;
            }

            x += dx;
            y += dy;
            repaint();
        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...