无法在 java 中绘制形状
Can't draw shapes in java
我很确定这段代码应该在屏幕上的文字旁边绘制一个椭圆形。然而,这个字全部出现了,屏幕的其余部分是黑色的。这似乎发生在任何原始形状上。我想我对 java 相当了解,但图形方面的东西一直让我感到困惑。我对此束手无策,如有任何帮助,我们将不胜感激。
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.util.ArrayList;
public class Game extends JPanel implements Runnable {
int W = 4;
int H = 3;
int windowSize = 300;
boolean running;
static boolean drawHitBoxes = true;
int FPSLimit = 30;
private Thread thread;
private BufferedImage buffer;
private Graphics2D g;
public Game() {
super();
setPreferredSize(new Dimension(W * windowSize, H * windowSize));
setFocusable(true);
requestFocus();
}
public void addNotify() {
super.addNotify();
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
public void run() {
running = true;
buffer = new BufferedImage(W * windowSize, H * windowSize,
BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) buffer.getGraphics();
// citList.add(new Citizen(200, 200, "Joe"));
long startTime;
long waitTime;
long frameTime = 1000 / FPSLimit; // /How long one frame should take
long currentFrameTime;
while (running) {
startTime = System.nanoTime(); // record when loop starts
gameUpdate();
gameRender();
gameDraw();
// Calculate how long the current frame took
currentFrameTime = (System.nanoTime() - startTime) / 1000000;
waitTime = frameTime - currentFrameTime;
try {
Thread.sleep(waitTime);
} catch (Exception e) {
} // Sleep for the remaining time
}
}
private void gameUpdate() {
// for(Citizen i:citList){i.update();} //Update citizens
}
private void gameRender() {
g.setColor(Color.WHITE);
g.drawOval(100, 100, W - 100, H - 100);
g.setColor(Color.WHITE);
g.drawString("Text.", 100, 100);
System.out.println("Drawing white box.");
// for(Citizen i:citList){i.draw(g);} //Draw citizens
}
private void gameDraw() {
Graphics gMain = this.getGraphics();
gMain.drawImage(buffer, 0, 0, null);
}
}
g.drawOval(100, 100, W-100, H-100);
W 是 4,H 是 3,所以因为 W-100
是 -96 而 H-100
是 -97,所以你的第三个和第四个参数是负的,这对Graphics#drawOval(...)
方法,因为椭圆的宽度和高度怎么可能是负数。解决方案:确保在调用此方法时仅使用有意义的正参数。可能你想要的是:
// but you'll also want to avoid magic numbers such as 100 & 200 as well
g.drawOval(100, 100, W * windowSize - 200, H * windowSize - 200);
顺便说一句,我自己更喜欢使用被动图形,在 paintComponent 中绘图,每当我看到具有 Graphics 或 Graphics2D 实例字段的 Swing 代码时我都很害怕。此外,您的代码看起来不遵守 Swing 线程规则,因为它似乎是在 Swing 事件线程之外进行 Swing 调用。
我认为最好创建 paintComponent 方法并将您的 gameRender 和 gameDraw 转移到那里,并在您的 while 循环中用 repaint() 替换它们的方法调用。这是有效的代码。
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.util.ArrayList;
public class Game extends JPanel implements Runnable {
int W = 4;
int H = 3;
int windowSize = 300;
boolean running;
static boolean drawHitBoxes = true;
int FPSLimit = 30;
private Thread thread;
private BufferedImage buffer;
private Graphics2D g;
public Game() {
super();
setPreferredSize(new Dimension(W * windowSize, H * windowSize));
setFocusable(true);
requestFocus();
}
public void addNotify() {
super.addNotify();
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
public void run() {
running = true;
buffer = new BufferedImage(W * windowSize, H * windowSize,
BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) buffer.getGraphics();
// citList.add(new Citizen(200, 200, "Joe"));
long startTime;
long waitTime;
long frameTime = 1000 / FPSLimit; // /How long one frame should take
long currentFrameTime;
while (running) {
startTime = System.nanoTime(); // record when loop starts
gameUpdate();
//gameRender();
//gameDraw();
repaint();
// Calculate how long the current frame took
currentFrameTime = (System.nanoTime() - startTime) / 1000000;
waitTime = frameTime - currentFrameTime;
try {
Thread.sleep(waitTime);
} catch (Exception e) {
} // Sleep for the remaining time
}
}
private void gameUpdate() {
// for(Citizen i:citList){i.update();} //Update citizens
}
private void gameRender() {
g.setColor(Color.WHITE);
//g.drawOval(100, 100, W - 100, H - 100);
g.drawOval(100, 100, 100, 100);
g.setColor(Color.WHITE);
g.drawString("Text.", 100, 100);
//System.out.println("Drawing white box.");
// for(Citizen i:citList){i.draw(g);} //Draw citizens
}
private void gameDraw(Graphics gMain) {
//Graphics gMain = this.getGraphics();
gMain.drawImage(buffer, 0, 0, null);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
gameRender();
gameDraw(g);
}
}
正如@Hovercraft 在他的回答中指出的那样,代码`g.drawOval(100, 100, W - 100, H - 100); 中的 W-100 和 H-100将产生负数。我不确切知道你想要在那里产生什么值,但我只是用 100 替换它们只是为了消除错误。
我很确定这段代码应该在屏幕上的文字旁边绘制一个椭圆形。然而,这个字全部出现了,屏幕的其余部分是黑色的。这似乎发生在任何原始形状上。我想我对 java 相当了解,但图形方面的东西一直让我感到困惑。我对此束手无策,如有任何帮助,我们将不胜感激。
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.util.ArrayList;
public class Game extends JPanel implements Runnable {
int W = 4;
int H = 3;
int windowSize = 300;
boolean running;
static boolean drawHitBoxes = true;
int FPSLimit = 30;
private Thread thread;
private BufferedImage buffer;
private Graphics2D g;
public Game() {
super();
setPreferredSize(new Dimension(W * windowSize, H * windowSize));
setFocusable(true);
requestFocus();
}
public void addNotify() {
super.addNotify();
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
public void run() {
running = true;
buffer = new BufferedImage(W * windowSize, H * windowSize,
BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) buffer.getGraphics();
// citList.add(new Citizen(200, 200, "Joe"));
long startTime;
long waitTime;
long frameTime = 1000 / FPSLimit; // /How long one frame should take
long currentFrameTime;
while (running) {
startTime = System.nanoTime(); // record when loop starts
gameUpdate();
gameRender();
gameDraw();
// Calculate how long the current frame took
currentFrameTime = (System.nanoTime() - startTime) / 1000000;
waitTime = frameTime - currentFrameTime;
try {
Thread.sleep(waitTime);
} catch (Exception e) {
} // Sleep for the remaining time
}
}
private void gameUpdate() {
// for(Citizen i:citList){i.update();} //Update citizens
}
private void gameRender() {
g.setColor(Color.WHITE);
g.drawOval(100, 100, W - 100, H - 100);
g.setColor(Color.WHITE);
g.drawString("Text.", 100, 100);
System.out.println("Drawing white box.");
// for(Citizen i:citList){i.draw(g);} //Draw citizens
}
private void gameDraw() {
Graphics gMain = this.getGraphics();
gMain.drawImage(buffer, 0, 0, null);
}
}
g.drawOval(100, 100, W-100, H-100);
W 是 4,H 是 3,所以因为 W-100
是 -96 而 H-100
是 -97,所以你的第三个和第四个参数是负的,这对Graphics#drawOval(...)
方法,因为椭圆的宽度和高度怎么可能是负数。解决方案:确保在调用此方法时仅使用有意义的正参数。可能你想要的是:
// but you'll also want to avoid magic numbers such as 100 & 200 as well
g.drawOval(100, 100, W * windowSize - 200, H * windowSize - 200);
顺便说一句,我自己更喜欢使用被动图形,在 paintComponent 中绘图,每当我看到具有 Graphics 或 Graphics2D 实例字段的 Swing 代码时我都很害怕。此外,您的代码看起来不遵守 Swing 线程规则,因为它似乎是在 Swing 事件线程之外进行 Swing 调用。
我认为最好创建 paintComponent 方法并将您的 gameRender 和 gameDraw 转移到那里,并在您的 while 循环中用 repaint() 替换它们的方法调用。这是有效的代码。
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.util.ArrayList;
public class Game extends JPanel implements Runnable {
int W = 4;
int H = 3;
int windowSize = 300;
boolean running;
static boolean drawHitBoxes = true;
int FPSLimit = 30;
private Thread thread;
private BufferedImage buffer;
private Graphics2D g;
public Game() {
super();
setPreferredSize(new Dimension(W * windowSize, H * windowSize));
setFocusable(true);
requestFocus();
}
public void addNotify() {
super.addNotify();
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
public void run() {
running = true;
buffer = new BufferedImage(W * windowSize, H * windowSize,
BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) buffer.getGraphics();
// citList.add(new Citizen(200, 200, "Joe"));
long startTime;
long waitTime;
long frameTime = 1000 / FPSLimit; // /How long one frame should take
long currentFrameTime;
while (running) {
startTime = System.nanoTime(); // record when loop starts
gameUpdate();
//gameRender();
//gameDraw();
repaint();
// Calculate how long the current frame took
currentFrameTime = (System.nanoTime() - startTime) / 1000000;
waitTime = frameTime - currentFrameTime;
try {
Thread.sleep(waitTime);
} catch (Exception e) {
} // Sleep for the remaining time
}
}
private void gameUpdate() {
// for(Citizen i:citList){i.update();} //Update citizens
}
private void gameRender() {
g.setColor(Color.WHITE);
//g.drawOval(100, 100, W - 100, H - 100);
g.drawOval(100, 100, 100, 100);
g.setColor(Color.WHITE);
g.drawString("Text.", 100, 100);
//System.out.println("Drawing white box.");
// for(Citizen i:citList){i.draw(g);} //Draw citizens
}
private void gameDraw(Graphics gMain) {
//Graphics gMain = this.getGraphics();
gMain.drawImage(buffer, 0, 0, null);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
gameRender();
gameDraw(g);
}
}
正如@Hovercraft 在他的回答中指出的那样,代码`g.drawOval(100, 100, W - 100, H - 100); 中的 W-100 和 H-100将产生负数。我不确切知道你想要在那里产生什么值,但我只是用 100 替换它们只是为了消除错误。