Java实现小球在窗口弹跳(Bouncing Balls App)

本篇博客将主要介绍一个名为 Bouncing Balls App 的小程序,使用 Java 编写,主要运用了 GUI 编程和多线程的知识点。

目录

# GUI 部分

# 多线程部分


首先,我们来了解一下这个小程序做了什么。

这个小程序可以在自动生成的窗口中生成大量的彩色球,每个球都会自动以一定的速度在窗口中弹跳。

接着,我们来看一下实现这个小程序的关键代码。

# GUI 部分

图形用户界面(GUI)部分使用了 Java 原生的 Swing 库实现。

public class BouncingBallsApp extends JFrame {
    private JPanel ballPanel;
    private final int numBalls = 100;
    private Ball[] balls;

    public BouncingBallsApp() {
        setTitle("Bouncing Balls Application");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(800, 600);
        setLocationRelativeTo(null);

        ballPanel = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                if (balls != null) {
                    for (Ball ball : balls) {
                        ball.draw(g);
                    }
                }
            }
        };

        JButton startButton = new JButton("开始");
        JButton closeButton = new JButton("关闭");

        // 按钮点击事件部分在下面讲解

        setLayout(new BorderLayout());
        add(ballPanel, BorderLayout.CENTER);
        JPanel buttonPanel = new JPanel();
        buttonPanel.add(startButton);
        buttonPanel.add(closeButton);
        add(buttonPanel, BorderLayout.SOUTH);

        setVisible(true);
    }
}

可以看到,通过集成 `JFrame` 类实现了一个窗口,并在其中通过 `JPanel` 类实现了一个面板,用于绘制弹跳小球。在 `paintComponent()` 方法中,通过循环遍历 `balls` 数组中的元素,调用 `draw()` 方法绘制小球。

# 多线程部分

在多线程部分中,也要自己编写一个名为 `Ball` 的类,然后实现 `Runnable` 接口(因为 Java 只支持 **单继承**,所以只能通过实现接口的方式来创建线程)。

这是 `Ball` 类的代码:

private class Ball implements Runnable {
    private JPanel ballPanel;
    private int x;
    private int y;
    private int dx;
    private int dy;
    private Color color;;
    private static final int BALL_SIZE = 20;

    public Ball(JPanel ballPanel) {
        this.ballPanel = ballPanel;
        Random r = new Random();
        x = r.nextInt(ballPanel.getWidth() - BALL_SIZE);
        y = r.nextInt(ballPanel.getHeight() - BALL_SIZE);
        dx = r.nextInt(10) + 1;
        dy = r.nextInt(10) + 1;
        color = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256));
    }

    @Override
    public void run() {
        while (true) {
            moveBall();
            repaint();

            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void moveBall() {
        if (x < 0 || x > ballPanel.getWidth() - BALL_SIZE) {
            dx = -dx;
        }
        if (y < 0 || y > ballPanel.getHeight() - BALL_SIZE) {
            dy = -dy;
        }

        x += dx;
        y += dy;
    }

    private void repaint() {
        ballPanel.repaint();
    }

    public void draw(Graphics g) {
        g.setColor(color);
        g.fillOval(x, y, BALL_SIZE, BALL_SIZE);
    }
}
```

然后在 `startBouncing()` 方法中,遍历 `balls` 数组中的所有元素,为每个小球(即每个 `Ball` 对象)启动一个线程,设置动画效果。

```
private void startBouncing() {
    balls = new Ball[numBalls];

    for (int i = 0; i < numBalls; i++) {
        balls[i] = new Ball(ballPanel);
        Thread thread = new Thread(balls[i]);
        thread.start();
    }
}

综上,本篇博客主要介绍了一个小程序 Bouncing Balls App,其中运用了 GUI 编程和多线程的知识点。如果你也想体验这个小程序,可以自己将代码编译运行后进行浏览。

下面是完整代码:

package 线程.小球页面;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

public class BouncingBallsApp extends JFrame {
    private JPanel ballPanel;
    private final int numBalls = 100;
    private Ball[] balls;

    public BouncingBallsApp() {
        setTitle("Bouncing Balls Application");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(800, 600);
        setLocationRelativeTo(null);

        ballPanel = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                if (balls != null) {
                    for (Ball ball : balls) {
                        ball.draw(g);
                    }
                }
            }
        };

        JButton startButton = new JButton("开始");
        JButton closeButton = new JButton("关闭");

        startButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                startBouncing();
            }
        });

        closeButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });

        setLayout(new BorderLayout());
        add(ballPanel, BorderLayout.CENTER);
        JPanel buttonPanel = new JPanel();
        buttonPanel.add(startButton);
        buttonPanel.add(closeButton);
        add(buttonPanel, BorderLayout.SOUTH);

        setVisible(true);
    }

    private void startBouncing() {
        balls = new Ball[numBalls];
        for (int i = 0; i < numBalls; i++) {
            balls[i] = new Ball(ballPanel);
            Thread thread = new Thread(balls[i]);
            thread.start();
        }
    }
    private class Ball implements Runnable {
        private JPanel ballPanel;
        private int x;
        private int y;
        private int dx;
        private int dy;
        private Color color;
        private static final int BALL_SIZE = 20;

        public Ball(JPanel ballPanel) {
            this.ballPanel = ballPanel;
            Random random = new Random();
            x = random.nextInt(ballPanel.getWidth() - BALL_SIZE);
            y = random.nextInt(ballPanel.getHeight() - BALL_SIZE);
            dx = random.nextInt(10) + 1;
            dy = random.nextInt(10) + 1;
            color = new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256));
        }

        @Override
        public void run() {
            while (true) {
                moveBall();
                repaint();

                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        private void moveBall() {
            if (x < 0 || x > ballPanel.getWidth() - BALL_SIZE) {
                dx = -dx;
            }
            if (y < 0 || y > ballPanel.getHeight() - BALL_SIZE) {
                dy = -dy;
            }

            x += dx;
            y += dy;
        }

        private void repaint() {
            ballPanel.repaint();
        }

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

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new BouncingBallsApp();
            }
        });
    }
}

下面是效果展示:

  • 28
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值