早上好,我正在构建一些基本的蛇游戏,以了解有关Java中的线程和图形的更多信息。在我的日食项目中,所有代码方面的工作都不完美,但足以满足我的喜好。现在,我尝试将项目从eclipse导出到可运行的.jar文件中,不知何故,框架的大小与我为其指定的大小不同,并且所有内容突然都大于其应有的大小,这也弄乱了我设置为“边框”的矩形”等等。我正在使用选项“将所需的库打包到生成的jar中”导出为可运行的JAR文件。任何人都知道为什么会这样,以及我可以做什么来解决它或优化程序以解决这些问题?这是框架使用的所有代码:
import java.awt.BasicStroke;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Grid extends Canvas{
private JFrame _container;
private int _size;
private int[] food;
private boolean running;
private boolean alive;
private Snake s;
private Rectangle _border;
private int score;
private int highscore;
private BufferStrategy bs;
public Grid() {
super();
_container = new JFrame("Snake Final");
_container.setSize(622,656);
_container.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
_container.setVisible(true);
setSize(600, 600);
setVisible(true);
_container.add(this);
createBufferStrategy(2);
bs = getBufferStrategy();
food = new int[2];
highscore = 0;
init();
}
private void init() {
_size = 30;
_border = new Rectangle(0,0,getWidth(),getHeight());
s = new Snake(_size, _border, this);
setKeyListener();
running = true;
generateFood();
run();
}
public void run() {
running = true;
while(running) {
s.update();
if(s.checkFood(food)) {
generateFood();
}
draw();
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
}
}
public void gameOver() {
alive = false;
if(score > highscore) {
highscore = score;
}
Graphics g = this.getGraphics();
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.white);
// g.drawLine(getWidth() / 2, 0, getWidth() / 2, getHeight());
// g.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2);
}
private void setKeyListener() {
this.addKeyListener(new KeyListener() {
@Override
public void keyPressed(KeyEvent arg0) {
if(arg0.getKeyCode() == KeyEvent.VK_W) {
if(running) {
if(s.getYDir() == 0) {
s.changeDirection(0, -1);
}
}
}
else if(arg0.getKeyCode() == KeyEvent.VK_S) {
if(running) {
if(s.getYDir() == 0) {
s.changeDirection(0, 1);
}
}
}
else if(arg0.getKeyCode() == KeyEvent.VK_A) {
if(running) {
if(s.getXDir() == 0) {
s.changeDirection(-1, 0);
}
}
}
else if(arg0.getKeyCode() == KeyEvent.VK_D) {
if(running) {
if(s.getXDir() == 0) {
s.changeDirection(1, 0);
}
}
}
else if(arg0.getKeyCode() == KeyEvent.VK_ENTER) {
alive = true;
s.setPosition(4 * _size, 4 * _size);
s.changeDirection(1, 0);
}
}
@Override
public void keyReleased(KeyEvent arg0) {}
@Override
public void keyTyped(KeyEvent arg0) {}
});
}
private void generateFood() {
int gridParts = (getWidth()/_size) - 4;
for(int i = 0; i < food.length; i++) {
food[i] = ((int) (Math.random() * (gridParts)) * _size) + 2 * _size;
}
}
private void draw() {
Graphics bg = bs.getDrawGraphics();
bg.clearRect(0, 0, getWidth(), getHeight());
if(alive) {
Graphics2D bg2d = (Graphics2D) bg;
bg2d.setStroke(new BasicStroke(_size*4));
bg2d.drawRect(0,0,getWidth(),getHeight());
s.show(bg2d);
// bg2d.fillRect(food[0] * _size, food[1] * _size, _size, _size);
score = s.getSize();
bg.setColor(Color.white);
bg.setFont(new Font("SansSerif", Font.PLAIN, 20));
bg.drawString(String.valueOf(score), 56, 35);
bg2d.setColor(Color.RED);
bg2d.fillRect((food[0] + 5), (food[1] + 5), _size - 10, _size - 10);
bg2d.dispose();
}
else {
bg.setColor(Color.black);
bg.fillRect(0, 0, getWidth(), getHeight());
bg.setColor(Color.white);
bg.setFont(new Font("SansSerif", Font.PLAIN, 20));
bg.drawString("Game Over", getWidth() / 2 - 55, getHeight() / 2 - 50);
bg.drawString("Score: " + String.valueOf(score), getWidth() / 2 - 55, getHeight() / 2 - 20);
bg.drawString("Highscore: " + String.valueOf(highscore), getWidth() / 2 - 55, getHeight() / 2 + 10);
bg.drawString("Press Enter to restart", getWidth() / 2 - 55, getHeight() / 2 +40);
}
bs.show();
bg.dispose();
}
}
对不起,它的代码确实很凌乱,但正如老话所说,如果它可以正常工作,为什么要重构它,也许还可以
_container = new JFrame("Snake Final");
_container.setSize(622,656);
_container.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
_container.setVisible(true);
setSize(600, 600);
setVisible(true);
_container.add(this);
您不应该对组件的大小进行硬编码。面板的大小将被忽略,因为Swing旨在与布局管理器一起使用。默认的BorderLayout将根据框架中可用的空间来设置画布的大小。
相反,您会向布局管理器提出建议。该代码应类似于:
_container = new JFrame("Snake Final");
_container.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//setSize(600, 600);
//setVisible(true); // not needed components are visible by default
setPreferredSize( new Dimension(600, 600) );
_container.add(this);
//_container.setSize(622,656);
_container.pack();
_container.setVisible(true);
因此将组件添加到pack()之前的框架中,并使该框架可见。然后,将通过pack()方法正确确定帧的大小。它将包括画布的首选大小,并将允许装饰框架(边框和标题栏)。
不知道这是否能解决创建Jar文件时遇到的问题(也许有一些属性可以覆盖打包的大小?),但这是对Swing框架更好的设计方法。