Java贪吃蛇游戏paintComponent()方法被触发两次的原因咨询
为什么Java Swing中paintComponent会被调用两次?
我在开发Java贪吃蛇游戏时,发现paintComponent方法被调用了两次。已经确定第一次调用是构造函数里的setBackground(Color.black)触发的,第二次调用发生在startGame()方法执行之后(因为苹果坐标已更新,说明调用在newApple()之后),想弄清楚第二次调用的具体原因。
相关代码如下:
GamePanelMultiplayer() { random = new Random(); this.setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT)); this.setBackground(Color.black); this.setFocusable(true); this.addKeyListener(new MyKeyAdapter()); startGame(); } public void startGame(){ newApple(); running = true; timer = new Timer(DELAY, this); timer.start(); } // 设置新苹果的坐标 public void newApple(){ appleX = random.nextInt(SCREEN_WIDTH/UNIT_SIZE)*UNIT_SIZE; appleY = random.nextInt(SCREEN_HEIGHT/UNIT_SIZE)*UNIT_SIZE; } public void paintComponent(Graphics g){ super.paintComponent(g); g.setColor(Color.darkGray); draw(g); } public void draw(Graphics g){ System.out.println("Draw has been called"); if(running) { // 绘制网格以可视化游戏区域 for(int i=0; i<=SCREEN_HEIGHT/UNIT_SIZE; i++) { g.drawLine(i*UNIT_SIZE, 0, i*UNIT_SIZE, SCREEN_HEIGHT); g.drawLine(0, i*UNIT_SIZE, SCREEN_WIDTH, i*UNIT_SIZE); } // 绘制苹果 g.setColor(Color.red); g.fillOval(appleX, appleY, UNIT_SIZE, UNIT_SIZE); } }
原因分析
- 第一次调用:正如你判断的,
setBackground(Color.black)会触发组件的重绘请求——背景色变更后,Swing需要重新渲染组件的背景区域,因此调用paintComponent。 - 第二次调用:这是Swing组件首次显示时的默认行为。当你的
GamePanelMultiplayer组件被添加到窗口容器(比如JFrame)并完成布局后,Swing的渲染系统会自动触发一次完整的重绘,确保组件显示最新状态。你在startGame()中调用了newApple()更新了苹果坐标,这次重绘正好把新的苹果位置绘制出来,所以你会看到调用发生在newApple()之后。另外,timer.start()本身不会立即触发paintComponent(定时器第一次触发是在DELAY毫秒后),所以第二次调用的核心原因是组件首次显示的强制重绘。
补充说明:Swing中很多操作都会异步触发repaint(),比如设置组件尺寸、焦点状态、添加到容器等,这些操作最终都会调用paintComponent。对于你的场景,第二次调用属于组件初始化完成后,Swing确保界面正确显示的必要步骤,完全符合预期。
内容的提问来源于stack exchange,提问作者Alexandru Lolea
相关产品推荐
相关产品推荐

