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

调用JPanel的repaint实现淡入动画时子组件偏移如何解决

问题解决

问题根源

  • 未开启JPanel的透明属性:JPanel默认opaque属性为true,Swing会默认该组件绘制区域完全不透明,不需要处理下层内容。你设置了透明背景色但没有调用setOpaque(false),会导致重绘区域计算异常,最终触发子组件偏移。
  • 淡入实现逻辑不合理:在paintChildren之后叠加半透明黑色的实现方式,不仅性能开销更高,还可能出现绘制冲突。

修复方案

直接通过AlphaComposite控制整个面板的透明度实现淡入,同时开启面板透明属性即可解决偏移问题,修改后的完整代码如下:

public class PlayAgainScreen extends JPanel implements ActionListener {
    private final int UNIT_SIZE;
    private final Timer timer;
    private int actPer = 0;

    public PlayAgainScreen(SnakePanel snakePanel, boolean justLaunched) {
        this.UNIT_SIZE = SnakePanel.UNIT_SIZE;
        this.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        this.setPreferredSize(new Dimension(UNIT_SIZE * 20, UNIT_SIZE * 15));
        // 开启面板透明属性,修复重绘区域计算异常
        this.setOpaque(false);
        PlayButton playButton = new PlayButton(snakePanel, justLaunched);
        Image image = new ImageIcon(Objects.requireNonNull(getClass().getClassLoader().getResource("snake_logo.png"))).getImage();
        image = image.getScaledInstance((int) (this.getPreferredSize().height * 0.5), (int) (this.getPreferredSize().height * 0.5), Image.SCALE_SMOOTH);
        JLabel label = new JLabel(new ImageIcon(image));
        gbc.insets = new Insets(0, UNIT_SIZE, 0, 0);
        gbc.gridx = 0;
        gbc.gridy = 0;
        this.add(playButton, gbc);
        gbc.gridx = 1;
        this.add(label, gbc);
        timer = new Timer(17, this);
        timer.start();
    }

    @Override
    public void paint(Graphics g) {
        Graphics2D g2D = (Graphics2D) g;
        // 保存原始的Composite配置
        Composite oldComposite = g2D.getComposite();
        // 设置透明度,actPer从0到30,透明度从0到1实现淡入
        g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, actPer / 30f));
        // 绘制面板所有内容(包括背景、子组件)
        super.paint(g);
        // 还原原始配置,避免影响其他组件绘制
        g2D.setComposite(oldComposite);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2D = (Graphics2D) g;
        g2D.setColor(new Color(0x543200));
        g2D.fillRoundRect(0, 0, this.getWidth(), this.getHeight(), UNIT_SIZE, UNIT_SIZE);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        actPer++;
        repaint();
        if (actPer == 30) {
            timer.stop();
        }
    }
}

内容的提问来源于stack exchange,提问作者Gal Arzi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 02:36:04