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

Java Swing中JPanel调用repaint()未触发paintComponent()问题

问题诊断与解决

核心问题:你的PixelArtCreator面板未被正确布局显示,导致repaint()无法触发paintComponent()。以下是具体问题点和修复方案:

问题1:空布局导致面板不可见

主类中frame.setLayout(null)使用了空布局,但未给添加的PixelArtCreator面板设置边界(Bounds)。空布局下Swing不会自动管理组件的位置和大小,面板默认尺寸为(0,0,0,0),相当于完全隐藏,自然不会触发绘制逻辑。

问题2:paintComponent未调用父类方法

重写paintComponent时必须调用super.paintComponent(g),这是Swing绘制机制的核心要求——父类方法负责完成面板清空、UI委托处理等基础绘制工作,缺失会导致绘制链断裂,即使面板显示也可能出现画面残留、不更新等异常。

问题3:JFrame大小设置不严谨

手动计算frame.setSize(PixelArtCreator.width+14, PixelArtCreator.height+38)依赖系统窗口装饰尺寸,不同系统(Windows/macOS/Linux)的边框、标题栏高度存在差异,容易导致面板显示不全。改用pack()方法让JFrame自动适配组件首选尺寸更稳妥。


修复后的完整代码

PixelArtCreator类修复

package de.luiskun.handling;

import de.luiskun.UtilityTool;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;

public class PixelArtCreator extends JPanel implements Runnable{

    BufferedImage imgBefore;
    Thread gameThread;

    public static final int width = 900, height = 500;

    int fps = 60;

    public PixelArtCreator() {
        this.setPreferredSize(new Dimension(width, height));
        this.setDoubleBuffered(true);
        this.setLayout(null);
        this.setFocusable(true);

        imgBefore = UtilityTool.SetupImage("res/preparation/00001", 512, 512);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g); // 必须调用父类基础绘制方法
        System.out.println(1);
        Graphics2D g2 = (Graphics2D) g;
        if(imgBefore != null) {
            g2.drawImage(imgBefore, 10, 10, 512, 512, null);
        }
        g2.dispose(); // 释放Graphics2D资源
    }

    public void startGameThread() {
        gameThread = new Thread(this);
        gameThread.start();
    }

    @Override
    public void run() {
        double drawInterval = 1000000000 / fps;
        double delta = 0;
        long lastTime = System.nanoTime(); // 改用long类型避免浮点数精度问题
        long currentTime;
        while (gameThread != null) {
            currentTime = System.nanoTime();
            delta += (currentTime - lastTime) / drawInterval;
            lastTime = currentTime;
            if (delta >= 1) {
                System.out.println(2);
                this.repaint();
                delta--;
            }
        }
    }
}

Main类修复

package de.luiskun;

import de.luiskun.handling.PixelArtCreator;

import javax.swing.*;

public class Main {

    public static void main(String[] args) {
        // Swing组件必须在事件调度线程(EDT)中创建,避免线程安全问题
        SwingUtilities.invokeLater(Main::new);
    }

    public Main() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);

        PixelArtCreator s = new PixelArtCreator();
        frame.add(s);
        frame.pack(); // 自动适配组件首选尺寸
        frame.setVisible(true);

        s.startGameThread();
    }
}

额外优化说明

  • 新增SwingUtilities.invokeLater(Main::new):Swing要求所有组件的创建和操作必须在**事件调度线程(EDT)**中执行,否则可能出现UI卡顿、线程安全异常,之前的代码直接在main线程创建组件不符合规范。
  • run()方法中时间变量改为long:避免浮点数精度损耗,计时逻辑更准确。
  • 新增g2.dispose():手动释放Graphics2D资源,优化内存占用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 04:10:15