为何repaint()方法未调用paintComponent()?矩形无法显示
问题原因与解决步骤
核心问题:未将GameWindow面板添加到窗口容器
你创建了GameWindow实例(它是JPanel的子类),但在setWindow方法里只创建了JFrame,却没有把当前GameWindow对象添加到JFrame的内容面板中。Swing只会绘制处于容器层级内的组件,所以你的paintComponent方法完全没机会被调用。
修复步骤
- 在
setWindow方法中添加window.add(this);,将当前GameWindow面板加入到JFrame中。 - 移除
window.setPreferredSize(...),转而在GameWindow的构造方法里设置自身的首选尺寸:setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT));,让JFrame根据面板尺寸自动调整大小。 - 删掉
paintComponent中的g2.dispose()——传入的Graphics对象由Swing管理,手动释放会导致后续绘制异常。 - 在动画循环中添加休眠逻辑,避免无限循环占用过多CPU资源,比如每帧休眠16ms(约60帧/秒)。
修复后的完整代码
Main类
public class Main { GameWindow gw; Main() { gw = new GameWindow(); } void start() { gw.setWindow(); } public static void main(String[] args) { new Main().start(); } }
GameWindow类
import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JPanel; public class GameWindow extends JPanel implements Runnable { final int ORIGINAL_TILE_SIZE = 16; final int SCALE = 3; final int TILE_SIZE = ORIGINAL_TILE_SIZE * SCALE; final int MAX_SCREEN_COLUMNS = 16; final int MAX_SCREEN_ROWS = 12; final int SCREEN_WIDTH = TILE_SIZE * MAX_SCREEN_COLUMNS; final int SCREEN_HEIGHT = TILE_SIZE * MAX_SCREEN_ROWS; Thread animation; public GameWindow() { // 面板自身设置首选尺寸 setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT)); setBackground(Color.black); } void setWindow() { JFrame window = new JFrame(); window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); window.setResizable(false); window.setTitle("Avontuur"); // 关键:将当前面板添加到窗口容器 window.add(this); ImageIcon icon = new ImageIcon("C:\\Users\\Rick\\Desktop\\Star.png"); window.setIconImage(icon.getImage()); window.pack(); window.setLocationRelativeTo(null); window.setVisible(true); startAnimation(); } void startAnimation() { animation = new Thread(this); animation.start(); } @Override public void run() { while (animation != null) { update(); repaint(); // 添加休眠控制帧率 try { Thread.sleep(16); } catch (InterruptedException e) { e.printStackTrace(); } } } public void update() { } @Override public void paintComponent(final Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; g2.setColor(Color.white); g2.fillRect(100, 100, TILE_SIZE, TILE_SIZE); // 不要手动释放传入的Graphics对象 // g2.dispose(); } }
额外注意事项
- 保持
paintComponent上的@Override注解,编译器会帮你校验方法签名是否符合Swing的要求。 repaint()方法会自动将绘制请求放入Swing的事件调度线程(EDT)中执行,无需手动处理线程同步问题。
内容的提问来源于stack exchange,提问作者Rickvdp
相关产品推荐
相关产品推荐

