【问题标题】:Java cannot render Menu state (Java GUI)Java 无法呈现菜单状态(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 只是猜测工作

标签: java swing user-interface awt classcastexception


【解决方案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());
        }

    }
}

如果您仍然有问题,请继续提供一个可运行的示例来演示您的问题

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-10
    • 2018-06-02
    • 1970-01-01
    • 2010-12-03
    • 2016-05-15
    • 1970-01-01
    相关资源
    最近更新 更多