我相信我的代码会描述我写的内容,但问题是,当我运行它时,我得到了臭名昭着的“线程中的异常”Animator“java.lang.IllegalArgumentException:Width(0)and height(0 )不能是< = 0“错误。我已经搜索了答案,但尚未找到原因。
package com.shparki.TowerDefense;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements Runnable{
//==================== PROGRAM VARIABLES ====================//
private static final int WIDTH = 300;
private static final int HEIGHT = WIDTH / 16 * 9;
private static final int SCALE = 4;
private static final int TARGET_FPS = 45;
private static final int PERIOD = 1000 / TARGET_FPS;
private boolean debug = true;
private volatile boolean running = false;
private volatile boolean gameOver = false;
private volatile boolean paused = false;
private Thread animator;
private TowerDefense frame;
private double currentFPS;
//==================== PROGRAM METHODS ====================//
public GamePanel(TowerDefense td){
frame = td;
setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setVisible(true);
}
public void addNotify(){
super.addNotify();
startGame();
}
public void startGame(){
if (!running && animator == null){
animator = new Thread(this, "Animator");
animator.start();
}
}
public void stopGame(){
running = false;
}
public void run(){
running = true;
Long beforeTime, timeDiff, sleepTime;
while(running){
beforeTime = System.currentTimeMillis();
update();
render();
paintScreen();
timeDiff = System.currentTimeMillis() - beforeTime;
sleepTime = PERIOD - timeDiff;
if (sleepTime <= 0){
sleepTime = 5L;
}
currentFPS = (1000 / ( timeDiff + sleepTime ));
try{
Thread.sleep(sleepTime);
} catch (InterruptedException ex) { ex.printStackTrace(); }
}
System.exit(0);
}
//==================== DRAWING METHODS ====================//
private Graphics dbg;
private Image dbImage;
public void paintComponenet(Graphics g){
super.paintComponent(g);
if (dbImage != null){
g.drawImage(dbImage, 0, 0, null);
}
}
public void paintScreen(){
Graphics g;
try{
g = this.getGraphics();
if (g != null & dbImage != null){
g.drawImage(dbImage, 0, 0, null);
}
Toolkit.getDefaultToolkit().sync();
g.dispose();
} catch (Exception ex) { System.out.println("Graphics context error: " + ex); }
}
public void doubleBuffer(){
if (dbImage == null){
dbImage = createImage(getWidth(), getHeight());
if (dbImage == null){
System.out.println("dbImage is null");
return;
} else {
dbg = dbImage.getGraphics();
}
}
}
//==================== UPDATE METHODS ====================//
public void update(){
}
//==================== RENDER METHODS ====================//
public void render(){
doubleBuffer();
Graphics2D g2d = (Graphics2D) dbg;
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
}
这是我的框架类:
package com.shparki.TowerDefense;
import java.awt.BorderLayout;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.JFrame;
public class TowerDefense extends JFrame implements WindowListener{
public TowerDefense(String name){
super(name);
setResizable(false);
setLayout(new BorderLayout());
add(new GamePanel(this), BorderLayout.CENTER);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
public void windowActivated(WindowEvent arg0) { }
public void windowClosed(WindowEvent arg0) { }
public void windowClosing(WindowEvent arg0) { }
public void windowDeactivated(WindowEvent arg0) { }
public void windowDeiconified(WindowEvent arg0) { }
public void windowIconified(WindowEvent arg0) { }
public void windowOpened(WindowEvent arg0) { }
public static void main(String[] args){
new TowerDefense("Tower Defense Game");
}
}
答案 0 :(得分:1)
JFrame
尚未打包,然后在GamePanel
dbImage = createImage(getWidth(), getHeight());
为0x0
生成JPanel
维度。
原因是,一旦为组件设置了父组件,Swing几乎立即调用addNotify(其中startGame
所在的位置)。
您可以在调用pack后显式调用startGame
。
add(gamePanel, BorderLayout.CENTER);
pack();
gamePanel.startGame();