Java Swing三球移动动画残影及白屏问题求助
解决Swing动画残影和空白问题
问题出在哪
- 直接在
JFrame上重写paint方法:Swing顶层窗口的paint方法负责绘制标题栏、边框等组件,直接在此画动画会打乱绘制流程,导致旧图像残留形成残影。 - 未清除旧画面:每次绘制新位置的小球前,没有清空上一帧的内容,旧小球图像会残留。
panel2未初始化:代码中仅声明了panel2但未创建实例,设置为内容面板相当于空容器,实际绘制直接在JFrame上,不符合Swing的绘制规范。- 在JFrame的
paint中调用super.paint(g):这会触发整个窗口的重绘,包括清空内容区域,导致频繁出现空白。
正确的做法
采用Swing推荐的动画实现方式:自定义JPanel子类,重写其paintComponent方法,利用super.paintComponent(g)自动清除背景,将动画逻辑封装在面板中。
修改后的完整代码
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class Animation extends JFrame { public Animation() { this.setTitle("MausKampf"); this.setSize(500, 500); this.setResizable(false); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // 添加自定义动画面板作为内容容器 this.add(new AnimationPanel()); this.setVisible(true); } // 封装动画逻辑与绘制的自定义面板 class AnimationPanel extends JPanel { int maus1x = 110; int maus1y = 350; int maus2x = 55; int maus2y = 350; int maus3x = 0; int maus3y = 350; Timer timer = new Timer(100, new TimeListener()); public AnimationPanel() { timer.start(); } @Override protected void paintComponent(Graphics g) { // 调用父类方法清除上一帧画面,解决残影的核心步骤 super.paintComponent(g); Graphics2D g2D = (Graphics2D) g; // 绘制背景线条 g2D.setColor(Color.black); g2D.drawLine(0, 400, 500, 400); g2D.drawLine(0, 350, 225, 350); g2D.drawLine(275, 350, 500, 350); g2D.drawLine(225, 350, 225, 0); g2D.drawLine(275, 350, 275, 0); // 绘制三个小球 g2D.setPaint(Color.CYAN); g2D.fillOval(maus1x, maus1y, 50, 50); g2D.setPaint(Color.GREEN); g2D.fillOval(maus2x, maus2y, 50, 50); g2D.setPaint(Color.RED); g2D.fillOval(maus3x, maus3y, 50, 50); } public void move() { maus1x += 4; maus2x += 4; maus3x += 4; if (maus1x > 325) { timer.stop(); } // 触发面板重绘,更新动画帧 repaint(); } class TimeListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { move(); } } } public static void main(String[] args) { // 遵循Swing线程安全规范,在EDT线程启动窗口 SwingUtilities.invokeLater(() -> new Animation()); } }
核心修改说明
- 自定义动画面板:将所有绘制和动画逻辑封装在
AnimationPanel中,符合Swing的组件职责划分,不会干扰窗口本身的绘制流程。 - 使用
paintComponent替代paint:该方法专门用于绘制面板内容,super.paintComponent(g)会自动清空面板背景,彻底解决残影问题。 - 移除无效的
panel2:替换为初始化完成的自定义动画面板,避免空指针异常。 - EDT线程启动窗口:通过
SwingUtilities.invokeLater启动窗口,符合Swing线程安全要求,避免潜在的UI卡顿或绘制错误。
内容的提问来源于stack exchange,提问作者schlachsahne
相关产品推荐
相关产品推荐

