Java 无法呈现菜单状态(Java GUI)
Posted
技术标签:
【中文标题】Java 无法呈现菜单状态(Java GUI)【英文标题】:Java cannot render Menu state (Java GUI) 【发布时间】:2021-08-11 17:30:06 【问题描述】:请阅读下方的最新更新
所以我正在尝试制作一个砖块破坏游戏,虽然在游戏玩法方面一切正常,但我在添加菜单系统时遇到了麻烦。基本上这就是我的代码的工作方式
public class Game extends Canvas implements Runnable
public Graphics g;
private Menu menu;
protected Ball ball;
protected Player player;
protected BufferedImage image;
protected BufferStrategy bufferStrategy;
protected Thread thread;
protected JFrame frame;
protected volatile boolean running, gameOver;
private enum STATE
MENU,
GAME,
ABOUT,
OPTIONS,
;
private STATE State = STATE.MENU;
public Game()
//Set the Jframe
private void init()
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
requestFocus();
menu = new Menu();
//init everything else aswell
public void update()
//Update every moving object
@Override
public void run()
init();
long initialTime = System.nanoTime();
double timePerFrame = 1000000000/FPS;
double delta = 0;
int ticks = 0;
long timer = 0;
while (running)
long currentTime = System.nanoTime();
long elapsedTime = currentTime - initialTime;
delta += elapsedTime/timePerFrame;
timer += elapsedTime;
if (delta >= 1)
update();
delta--;
ticks++;
render();
initialTime = currentTime;
if (timer >= 1000000000)
currentFPS = ticks;
ticks = 0;
timer = 0;
stop();
当我渲染 STATE GAME 中的所有内容时,它工作得很好,但是当我尝试添加执行 menu.draw(g) 的 else if 语句时,一切都崩溃了,我只是得到一个空白帧
这是我的渲染方式
public void render()
bufferStrategy = getBufferStrategy();
if (bufferStrategy == null)
createBufferStrategy(3);
return;
g = bufferStrategy.getDrawGraphics();
g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
g.setColor(BG_COLOR);
g.fillRect(0, 0, WIDTH, HEIGHT);
if(State == STATE.GAME)
player.draw(g);
ball.draw(g);
blockController.draw(g); **THESE WORK JUST FINE**
else if(State == STATE.MENU)
menu.draw(g); **DOES NOT WORK**
bufferStrategy.show();
g.dispose();
而我的Menu类在draw方法方面没有区别
public class Menu implements GUI
@Override
public void draw(Graphics g)
g.setFont(new Font("arial", Font.BOLD, 50));
g.setColor(Color.black);
g.drawString("MENU", Game.WIDTH / 2, 100);
知道为什么会发生这种情况,我正在做同样的渲染,但不断得到 线程“Thread-0”java.lang.ClassCastException 中的异常:无法将类 sun.java2d.NullSurfaceData 转换为类 sun.java2d.d3d.D3DSurfaceData 错误或 g 为 null 错误
我该如何解决这个问题?
更新 ----------------------------------
当我删除线条时,渲染中的 menu.draw() 工作
g.setFont(new Font("arial", Font.BOLD, 50));
g.setColor(Color.black);
g.drawString("MENU", Game.WIDTH / 2, 100);
而是添加类似的东西
g.setColor(Color.CYAN);
g.fillRect(5, 5, 200, 200);
这确实有效,但为什么 setfont、setColor 和 drawString 不起作用我不明白我也想添加按钮,但它们也不起作用。是不是因为我在渲染中使用g.fillRect(0, 0, WIDTH, HEIGHT);
行设置了整个框架,但是我可以添加像桨、球、砖这样的对象,但不能添加字符串或按钮?
【问题讨论】:
我的第一直觉是你应该评估“Font("arial", Font.BOLD, 50)”。由于“arial”似乎不是一个有效的字体名称,这可能导致没有文本被呈现 我还建议查看BufferStrategy JavaDocs,因为他们有一个很好的例子来说明如何使用 api @MadProgrammer 我删除了字体行仍然没有生命迹象 :( 感谢您建议文档,我将尝试像那里那样的循环结构。我的直觉是它与@有关987654322@ 但不明白,也许我会为菜单等创建新框架,然后如果游戏实际开始并且我们需要移动东西,就使用线程 难道我不使用可运行类中的 ticks 方法,也许我应该更改运行工作,以便刻度也必须在那里渲染它? @MadProgrammer minimal reproducible example 只是猜测工作 【参考方案1】:以下示例似乎运行良好。
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Test
public static void main(String[] args)
new Test();
public Test()
SwingUtilities.invokeLater(new Runnable()
@Override
public void run()
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setVisible(true);
);
public class TestPane extends Canvas
private Thread thread;
private volatile boolean render = false;
public TestPane()
@Override
public void addNotify()
super.addNotify();
start();
@Override
public void removeNotify()
super.removeNotify();
stop();
protected void start()
if (thread != null)
render = false;
try
thread.join();
catch (InterruptedException ex)
render = true;
thread = new Thread(new Runnable()
@Override
public void run()
while (render)
render();
try
Thread.sleep(16);
catch (InterruptedException ex)
);
thread.start();
protected void stop()
render = false;
if (thread == null)
return;
try
thread.join();
catch (InterruptedException ex)
thread = null;
@Override
public Dimension getPreferredSize()
return new Dimension(200, 200);
private Menu menu = new Menu();
protected void render()
BufferStrategy strategy = getBufferStrategy();
if (strategy == null)
createBufferStrategy(3);
strategy = getBufferStrategy();
if (strategy == null)
return;
do
// The following loop ensures that the contents of the drawing buffer
// are consistent in case the underlying surface was recreated
do
// Get a new graphics context every time through the loop
// to make sure the strategy is validated
Graphics graphics = strategy.getDrawGraphics();
graphics.setColor(Color.BLACK);
graphics.fillRect(0, 0, getWidth(), getHeight());
menu.render(graphics, getSize());
graphics.dispose();
// Repeat the rendering if the drawing buffer contents
// were restored
while (strategy.contentsRestored());
// Display the buffer
strategy.show();
// Repeat the rendering if the drawing buffer was lost
while (strategy.contentsLost());
public class Menu
public void render(Graphics g, Dimension bounds)
// This is probably going to cost you a lot of
// performance and it might be better to
// pre-create the font instead
g.setFont(new Font("Arial", Font.BOLD, 50));
g.setColor(Color.WHITE);
String text = "MENU";
FontMetrics fm = g.getFontMetrics();
g.drawString("MENU", (bounds.width - fm.stringWidth(text)) / 2, (bounds.height / 2) - fm.getAscent());
如果您仍然有问题,请继续提供一个可运行的示例来演示您的问题
【讨论】:
以上是关于Java 无法呈现菜单状态(Java GUI)的主要内容,如果未能解决你的问题,请参考以下文章