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

为何paintComponent重复绘制圆形?如何实现单圆弹跳动画?

解决圆形弹跳动画留下轨迹的问题

嘿,我一眼就揪出问题所在啦!你现在的代码之所以会出现一串圆形轨迹,而不是单个移动的圆形,是因为paintComponent方法里调用了错误的父类方法,导致每次重绘都没清除之前的画面。

问题根源

你在paintComponent里写了:

super.paintComponents(g);

注意这里是复数形式的paintComponents,这个方法是用来绘制容器内多个子组件的,不是用来清除当前组件旧画面的。正确的应该调用单数形式的paintComponent,它会帮你自动清除上一次的绘制内容,为新的绘制做好准备。

修正后的完整代码

把错误的那行代码替换掉,其他逻辑保持不变,修改后的代码如下:

class thePanel extends JPanel {
    int radius;
    int diameter;
    int x;
    int y;
    int dx;
    int dy;
    int timerInterval = 10;
    Timer timer;

    thePanel() {
        x = 0;
        y = 0;
        dx = 3;
        dy = 3;
        radius = 20;
        diameter = radius * 2;
        // 可以加一行设置背景色,让动画效果更稳定
        setBackground(Color.WHITE);
        timer = new Timer(timerInterval, new TimerListener());
        timer.start();
        repaint();
    }

    protected void paintComponent(Graphics g) {
        // 改成单数的paintComponent,清除旧画面
        super.paintComponent(g);
        g.drawRect(getWidth() / 2, 0, getWidth() / 2, getHeight());
        g.drawOval(this.x - radius, this.y - radius, diameter, diameter);
    }

    public void fixPosition() {
        x += dx;
        y += dy;
        if (x < radius) dx = Math.abs(dx);
        if (x > getWidth() - radius) dx = -Math.abs(dx);
        if (y < radius) dy = Math.abs(dy);
        if (y > getHeight() - radius) dy = -Math.abs(dy);
    }

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

额外小提示

我在构造方法里加了setBackground(Color.WHITE),如果你的面板默认是透明背景,有时候可能还是会出现绘制残留,设置一个纯色背景能让动画效果更稳定哦。

内容的提问来源于stack exchange,提问作者yara raffoul

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:24:22