欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > Java一个简单的反弹动画练习

Java一个简单的反弹动画练习

2025/7/4 3:17:23 来源:https://blog.csdn.net/mycqyjn/article/details/145066999  浏览:    关键词:Java一个简单的反弹动画练习

文章目录

  • 说明
  • 代码详解
    • 创建窗体代码
    • 创建绘图板
    • 创建线程
  • 运行结果
  • 完整代码

说明

做了一个小球和星型做反弹动画的窗体作为练习,分享给大家,为了方便和我一样的小白可以看的比较明白,所以尽量详细的标注了注释,希望能帮到同样在学习路上的朋友

代码详解

创建窗体代码

public class AnimationJFrame extends JFrame {//实例化属性private final DrawCircleAndStar drawCircleAndStar = new DrawCircleAndStar();//实例化图形绘制private final JButton jButton = new JButton();//实例化按钮private final AnimationRun animationRun = new AnimationRun();//实例化线程//设置绘图全局属性private int circleX = 0;//圆形的初始位置X坐标private int circleY = 10;//圆形的初始位置Y坐标private int circleXDirection = 1;//圆形运动X轴方向private int circleYDirection = 1;//圆形运动Y轴方向private int starX = 355;//星型的初始位置X坐标private int starY = 200;//星型的初始位置Y坐标private int starXDirection = 1;//星形运动X轴方向private int starYDirection = 1;//星形运动Y轴方向//构造方法构造窗体public AnimationJFrame(){//窗体基本设置Container conn = getContentPane();//建立窗体容器setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置窗体关闭方式setBounds(300,300,400,400);//设置窗体位置及大小setResizable(false);//窗体大小不可改变setLayout(null);//清空窗体布局管理器,不采用默认布局//创建动画布局JPanel jPanel = new JPanel();//实例化布局jPanel.setLayout(null);//清空布局的布局管理器,不采用默认布局jPanel.setBounds(10, 10, 365, 300);//动画布局的位置及大小jPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));//设置动画布局的边框jPanel.setBackground(Color.LIGHT_GRAY);//设置动画布局的底色//创建动画图形的标签容器JLabel jLabel = new JLabel();//实例化标签jLabel.setBounds(0,0,365,300);//设置动画标签的大小和位置//设置绘图标签drawCircleAndStar.setBackground(new Color(0,0,0,0));//设置绘图标签的背景透明drawCircleAndStar.setSize(365,300);//设置绘图标签的大小jLabel.add(drawCircleAndStar);//添加绘图板到标签jPanel.add(jLabel);//添加动画标签到动画布局//设置按键jButton.setText("开始");//设置按键显示文字jButton.setFont(new Font("黑体", Font.PLAIN, 14));//设置按键文字的字体jButton.setBounds(275, 320, 100, 22);//设置按键的位置和大小//添加原件到窗体容器conn.add(jPanel);//添加动漫布局到容器conn.add(jButton);//添加按钮到容器//给按钮添加监听jButton.addActionListener(e -> {if (e.getActionCommand().equals("开始")){jButton.setText("暂停一下");//更改按键文字animationRun.start();//启动线程}else if (e.getActionCommand().equals("暂停一下")){jButton.setText("继续");animationRun.pause();//暂停线程}else if (e.getActionCommand().equals("继续")){jButton.setText("暂停一下");animationRun.restart();//重启线程}});}

这里需要说明的是,代码中直接把窗体创建在构造方法中,但是直接在构造方法中设置窗体只适用于线程较简单的程序,如果在正式的项目中,应该避免这种写法,因为swing是线程不安全的,应该对窗体单独建立窗体方法容器,例如:

 public AnimationJFrame() {SwingUtilities.invokeLater(() -> {initUI();});}private void initUI() {//代码块...........}

创建绘图板

    //创建绘图板class DrawCircleAndStar extends JLabel{@Overridepublic void paintComponent(Graphics g){//重写paintComponentsuper.paintComponent(g);//继承父类的构造方法Graphics2D graphics2D = (Graphics2D) g;graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);//设置绘图抗锯齿//绘制圆形graphics2D.setColor(Color.RED);//设置填充颜色,红色graphics2D.fillOval(circleX,circleY,15,15);//设置圆形的位置和大小//绘制星型graphics2D.setColor(Color.BLUE);//设置填充色,蓝色//设置星型的属性int radius = 10;//设置星型的大小int[] xPoints = new int[10];//星型顶点的X坐标int[] yPoints = new int[10];//星型顶点的Y坐标//计算星型顶点的坐标及初始角度for (int i = 0; i < 10; i++) {double baseAngle = i * 2 * Math.PI / 10 + Math.PI / 2;//初始角度if (i % 2 == 0) {//外围顶点的坐标xPoints[i] = starX + (int) (radius * Math.cos(baseAngle));yPoints[i] = starY - (int) (radius * Math.sin(baseAngle));} else {//内部顶点的坐标xPoints[i] = starX + (int) (radius * Math.cos(baseAngle) * 0.5);yPoints[i] = starY - (int) (radius * Math.sin(baseAngle) * 0.5);}}Polygon star = new Polygon(xPoints, yPoints, 10);//绘制星型graphics2D.fillPolygon(star);//填充星型}}

创建绘图板,别的没有什么可说的,这里切记一点,无论绘图板继承自布局还是标签,相对的布局和标签是没有大小的,必须在窗体设置中,为它们设定尺寸,比如本代码中的

        drawCircleAndStar.setBackground(new Color(0,0,0,0));//设置绘图标签的背景透明drawCircleAndStar.setSize(365,300);//设置绘图标签的大小

如果不设置大小,将无法将绘图板图形显示到容器

创建线程

    //创建运行线程class AnimationRun extends Thread{boolean flag = false;//设置挂起标志synchronized void pause(){//暂停方法flag = true;}synchronized void restart(){//重启方法notifyAll();flag = false;}//重写run@Overridepublic void run(){//动画运行while (true) {//挂起区synchronized (this){while (flag){try {wait();//等待挂起} catch (InterruptedException e) {throw new RuntimeException(e);}}}//判断圆形运动方向if (circleX == 0) {circleXDirection = 1;} else if (circleX == 350) {circleXDirection = -1;}if (circleY == 0) {circleYDirection = 1;} else if (circleY == 285) {circleYDirection = -1;}//判断星型运动方向if (starX == 10){starXDirection = 1;}else if (starX == 355){starXDirection = -1;}if (starY == 10){starYDirection = 1;}else if (starY == 290){starYDirection = -1;}//设置绘图延迟try {Thread.sleep(10);} catch (InterruptedException e) {throw new RuntimeException(e);}//计算新的圆形位置和星型的位置circleX += circleXDirection;circleY += circleYDirection;starX += starXDirection;starY += starYDirection;//重绘绘图板drawCircleAndStar.repaint();}}}

synchronized相对来说并不是最优的选择,消耗较高,建议优化,另外一个这里重写的不是paint而是重写的paintComponent因为重写paintComponent只绘制图形主体,不会影响边框和背景,建议单独绘制元素的时候使用paintComponent而不是paint

运行结果

在这里插入图片描述

完整代码

import javax.swing.*;
import java.awt.*;public class AnimationJFrame extends JFrame {//实例化属性private final DrawCircleAndStar drawCircleAndStar = new DrawCircleAndStar();//实例化图形绘制private final JButton jButton = new JButton();//实例化按钮private final AnimationRun animationRun = new AnimationRun();//实例化线程//设置绘图全局属性private int circleX = 0;//圆形的初始位置X坐标private int circleY = 10;//圆形的初始位置Y坐标private int circleXDirection = 1;//圆形运动X轴方向private int circleYDirection = 1;//圆形运动Y轴方向private int starX = 355;//星型的初始位置X坐标private int starY = 200;//星型的初始位置Y坐标private int starXDirection = 1;//星形运动X轴方向private int starYDirection = 1;//星形运动Y轴方向//构造方法构造窗体public AnimationJFrame(){//窗体基本设置Container conn = getContentPane();//建立窗体容器setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置窗体关闭方式setBounds(300,300,400,400);//设置窗体位置及大小setResizable(false);//窗体大小不可改变setLayout(null);//清空窗体布局管理器,不采用默认布局//创建动画布局JPanel jPanel = new JPanel();//实例化布局jPanel.setLayout(null);//清空布局的布局管理器,不采用默认布局jPanel.setBounds(10, 10, 365, 300);//动画布局的位置及大小jPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));//设置动画布局的边框jPanel.setBackground(Color.LIGHT_GRAY);//设置动画布局的底色//创建动画图形的标签容器JLabel jLabel = new JLabel();//实例化标签jLabel.setBounds(0,0,365,300);//设置动画标签的大小和位置//设置绘图标签drawCircleAndStar.setBackground(new Color(0,0,0,0));//设置绘图标签的背景透明drawCircleAndStar.setSize(365,300);//设置绘图标签的大小jLabel.add(drawCircleAndStar);//添加绘图板到标签jPanel.add(jLabel);//添加动画标签到动画布局//设置按键jButton.setText("开始");//设置按键显示文字jButton.setFont(new Font("黑体", Font.PLAIN, 14));//设置按键文字的字体jButton.setBounds(275, 320, 100, 22);//设置按键的位置和大小//添加原件到窗体容器conn.add(jPanel);//添加动漫布局到容器conn.add(jButton);//添加按钮到容器//给按钮添加监听jButton.addActionListener(e -> {if (e.getActionCommand().equals("开始")){jButton.setText("暂停一下");//更改按键文字animationRun.start();//启动线程}else if (e.getActionCommand().equals("暂停一下")){jButton.setText("继续");animationRun.pause();//暂停线程}else if (e.getActionCommand().equals("继续")){jButton.setText("暂停一下");animationRun.restart();//重启线程}});}//创建绘图板class DrawCircleAndStar extends JLabel{@Overridepublic void paintComponent(Graphics g){//重写paintComponentsuper.paintComponent(g);//继承父类的构造方法Graphics2D graphics2D = (Graphics2D) g;graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);//设置绘图抗锯齿//绘制圆形graphics2D.setColor(Color.RED);//设置填充颜色,红色graphics2D.fillOval(circleX,circleY,15,15);//设置圆形的位置和大小//绘制星型graphics2D.setColor(Color.BLUE);//设置填充色,蓝色//设置星型的属性int radius = 10;//设置星型的大小int[] xPoints = new int[10];//星型顶点的X坐标int[] yPoints = new int[10];//星型顶点的Y坐标//计算星型顶点的坐标及初始角度for (int i = 0; i < 10; i++) {double baseAngle = i * 2 * Math.PI / 10 + Math.PI / 2;//初始角度if (i % 2 == 0) {//外围顶点的坐标xPoints[i] = starX + (int) (radius * Math.cos(baseAngle));yPoints[i] = starY - (int) (radius * Math.sin(baseAngle));} else {//内部顶点的坐标xPoints[i] = starX + (int) (radius * Math.cos(baseAngle) * 0.5);yPoints[i] = starY - (int) (radius * Math.sin(baseAngle) * 0.5);}}Polygon star = new Polygon(xPoints, yPoints, 10);//绘制星型graphics2D.fillPolygon(star);//填充星型}}//创建运行线程class AnimationRun extends Thread{boolean flag = false;//设置挂起标志synchronized void pause(){//暂停方法flag = true;}synchronized void restart(){//重启方法notifyAll();flag = false;}//重写run@Overridepublic void run(){//动画运行while (true) {//挂起区synchronized (this){while (flag){try {wait();//等待挂起} catch (InterruptedException e) {throw new RuntimeException(e);}}}//判断圆形运动方向if (circleX == 0) {circleXDirection = 1;} else if (circleX == 350) {circleXDirection = -1;}if (circleY == 0) {circleYDirection = 1;} else if (circleY == 285) {circleYDirection = -1;}//判断星型运动方向if (starX == 10){starXDirection = 1;}else if (starX == 355){starXDirection = -1;}if (starY == 10){starYDirection = 1;}else if (starY == 290){starYDirection = -1;}//设置绘图延迟try {Thread.sleep(10);} catch (InterruptedException e) {throw new RuntimeException(e);}//计算新的圆形位置和星型的位置circleX += circleXDirection;circleY += circleYDirection;starX += starXDirection;starY += starYDirection;//重绘绘图板drawCircleAndStar.repaint();}}}public static void main(String[] args) {new AnimationJFrame().setVisible(true);//启动程序}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com