You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Swing三球移动动画残影及白屏问题求助

解决Swing动画残影和空白问题

问题出在哪

  1. 直接在JFrame上重写paint方法:Swing顶层窗口的paint方法负责绘制标题栏、边框等组件,直接在此画动画会打乱绘制流程,导致旧图像残留形成残影。
  2. 未清除旧画面:每次绘制新位置的小球前,没有清空上一帧的内容,旧小球图像会残留。
  3. panel2未初始化:代码中仅声明了panel2但未创建实例,设置为内容面板相当于空容器,实际绘制直接在JFrame上,不符合Swing的绘制规范。
  4. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 14:01:30