按键移动矩形时run方法中repaint()与update()无效问题求助
问题描述
我需要让run方法(原描述误称loop())能够调用repaint(),但调用后无任何效果。此外,执行代码时run方法也未执行update()。尝试多种修改方式均无效,使用Eclipse作为开发IDE,因老师要求从零编写代码,不得使用游戏引擎。
相关代码
GamePanel类
package main; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import javax.swing.JPanel; public class GamePanel extends JPanel implements Runnable { private static final long serialVersionUID = 1L; final int originalTilesize=16; final int scale=3; final int tileSize=originalTilesize *scale; final int maxScreenRow=12; final int maxScreenCol=16; final int screenWidth=tileSize*maxScreenCol; final int screenHeight=tileSize*maxScreenRow; int FPS=60; KeyHandler keyH = new KeyHandler(); Thread gameThread; int playerX=100; int playerY=100; int playerSpeed=4; public GamePanel() { this.setPreferredSize(new Dimension(screenWidth,screenHeight)); this.setBackground(Color.black); this.setDoubleBuffered(true); this.addKeyListener(keyH); this.setFocusable(true); } public void startGameThread() { gameThread = new Thread(this); gameThread.start(); } public void run() { double drawInterval=1000000000/FPS; double nextDrawTime=System.nanoTime()+drawInterval; while (gameThread !=null) { update(); repaint(); try { double remainingTime=nextDrawTime-System.nanoTime(); remainingTime=remainingTime/1000000; if (remainingTime<0) { remainingTime=0; } Thread.sleep((long)remainingTime); nextDrawTime+=drawInterval; } catch (InterruptedException e) { e.printStackTrace(); } }; } public void update() { if (keyH.upPressed == true) { playerY-=playerSpeed; } else if(keyH.downPressed==true) { playerY +=playerSpeed; } else if(keyH.leftPressed==true) { playerX -=playerSpeed; } else if(keyH.rightPressed==true) { playerX +=playerSpeed; } } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2=(Graphics2D)g; g2.setColor(Color.white); g2.fillRect(playerX,playerY,tileSize,tileSize); g2.dispose(); } }
KeyHandler类
package main; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; public class KeyHandler implements KeyListener { public boolean upPressed,downPressed,leftPressed,rightPressed; public void keyTyped(KeyEvent e) { } public void keyPressed(KeyEvent e) { int code =e.getKeyCode(); if (code==KeyEvent.VK_W) { upPressed = true; } if (code==KeyEvent.VK_S) { downPressed=true; } if (code==KeyEvent.VK_A) { leftPressed=true; } if (code==KeyEvent.VK_D) { rightPressed=true; } } public void keyReleased(KeyEvent e) { int code=e.getKeyCode(); if (code==KeyEvent.VK_W) { upPressed = false; } if (code==KeyEvent.VK_S) { downPressed=false; } if (code==KeyEvent.VK_A) { leftPressed=false; } if (code==KeyEvent.VK_D) { rightPressed=false; } } }
解决方法
1. 确保启动游戏线程
你的GamePanel类中startGameThread()方法负责启动线程,但如果没有在主类中调用这个方法,run()根本不会执行。需要添加一个主类来初始化窗口并启动线程:
package main; import javax.swing.JFrame; public class Main { public static void main(String[] args) { JFrame frame = new JFrame(); GamePanel gamePanel = new GamePanel(); frame.add(gamePanel); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); // 必须调用此方法启动游戏线程 gamePanel.startGameThread(); } }
2. 删除手动释放Graphics资源的代码
在paintComponent方法中调用g2.dispose()会提前释放绘制资源,导致内容无法正常显示。Swing会自动管理Graphics资源,删除这行代码即可:
public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2=(Graphics2D)g; g2.setColor(Color.white); g2.fillRect(playerX,playerY,tileSize,tileSize); // 移除下面这行 // g2.dispose(); }
3. 优化线程循环(可选)
原run()方法的时间计算可能存在累积误差,可以改成更稳定的实现:
public void run() { long lastTime = System.nanoTime(); double tickInterval = 1000000000.0 / FPS; double delta = 0; while(gameThread != null){ long now = System.nanoTime(); delta += (now - lastTime) / tickInterval; lastTime = now; if(delta >= 1){ update(); repaint(); delta--; } } }
完成以上修改后,run()方法会正常执行update(),repaint()也能正确绘制玩家方块。
内容的提问来源于stack exchange,提问作者299792458
相关产品推荐
相关产品推荐

