java - 我怎样才能将一个物体设置为焦点

标签 java swing jbutton keylistener jdialog

我的游戏中有一个 Canvas 对象,但该对象未在焦点中设置,因此我的蛇没有在棋盘上移动 .

基本上我正在开发贪吃蛇游戏项目,我想要的是当从PlayGame.java JDialog单击播放按钮时,游戏应该开始,但我面临的问题是点击按钮游戏屏幕出现在窗口上,但蛇没有移动,所以有人建议我,你的 Canvas 对象在调用时都不处于焦点 >。 这就是为什么KeyLisener 无法监听按键/击键

这是声明和实现 Canvas 对象的类。

package org.psnbtech;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import org.psnbtech.GameBoard.TileType;
import org.psnbtech.Snake.Direction;


public class Engine extends KeyAdapter {

    private static final int UPDATES_PER_SECOND = 15;

    private static final Font FONT_SMALL = new Font("Arial", Font.BOLD, 20);

    private static final Font FONT_LARGE = new Font("Arial", Font.BOLD, 40);

    public Canvas canvas;

    public GameBoard board;

    public Snake snake;

    public int score;

    public boolean gameOver;


    public Engine(Canvas canvas) {
                this.canvas = canvas;
            this.board = new GameBoard();
        this.snake = new Snake(board);

        resetGame();

        canvas.addKeyListener(this);
                //new Engine(canvas).startGame();
    }


    public void startGame() {
        canvas.createBufferStrategy(2);

        Graphics2D g = (Graphics2D)canvas.getBufferStrategy().getDrawGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        long start = 0L;
        long sleepDuration = 0L;
        while(true) {
            start = System.currentTimeMillis();

            update();
            render(g);

            canvas.getBufferStrategy().show();

            g.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());

            sleepDuration = (1500L / UPDATES_PER_SECOND) - (System.currentTimeMillis() - start);

            if(sleepDuration > 0) {
                try {
                    Thread.sleep(sleepDuration);
                } catch(Exception e) {
                                    e.printStackTrace();
                }
            }
        }
    }

    public void update() {
        if(gameOver || !canvas.isFocusable()) {
            return;
        }
        TileType snakeTile = snake.updateSnake();
        if(snakeTile == null || snakeTile.equals(TileType.SNAKE)) {
            gameOver = true;
        } else if(snakeTile.equals(TileType.FRUIT)) {
            score += 10;
            spawnFruit();
        }
    }

    public void render(Graphics2D g) {
        board.draw(g);

        g.setColor(Color.WHITE);

        if(gameOver) {
            g.setFont(FONT_LARGE);
            String message = new String("Your Score: " + score);
            g.drawString(message, canvas.getWidth() / 2 - (g.getFontMetrics().stringWidth(message) / 2), 250);

            g.setFont(FONT_SMALL);
            message = new String("Press Enter to Restart the Game");
            g.drawString(message, canvas.getWidth() / 2 - (g.getFontMetrics().stringWidth(message) / 2), 350);
        } else {
            g.setFont(FONT_SMALL);
            g.drawString("Score:" + score, 10, 20);
        }
    }

    public void resetGame() {
        board.resetBoard();
        snake.resetSnake();
        score = 0;
        gameOver = false;
        spawnFruit();
    }

    public void spawnFruit() {
        int random = (int)(Math.random() * ((GameBoard.MAP_SIZE * GameBoard.MAP_SIZE) - snake.getSnakeLength())); // if '*' replace by '/' then only one fruit is there for snake

        int emptyFound = 0;
        int index = 0;
        while(emptyFound < random) {
            index++;
            if(board.getTile(index % GameBoard.MAP_SIZE, index / GameBoard.MAP_SIZE).equals(TileType.EMPTY)) { // if '/' replaced by '*' then nothing displays on the board 
                emptyFound++;
            }
        }
        board.setTile(index % GameBoard.MAP_SIZE, index / GameBoard.MAP_SIZE, TileType.FRUIT); // it also show nothing when replacing '/' by '/' 
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if((e.getKeyCode() == KeyEvent.VK_UP)||(e.getKeyCode() == KeyEvent.VK_W)) {
            snake.setDirection(Direction.UP);
        }
        if((e.getKeyCode() == KeyEvent.VK_DOWN)||(e.getKeyCode() == KeyEvent.VK_S)) {
            snake.setDirection(Direction.DOWN);
        }
        if((e.getKeyCode() == KeyEvent.VK_LEFT)||(e.getKeyCode() == KeyEvent.VK_A)) {
            snake.setDirection(Direction.LEFT);
        }
        if((e.getKeyCode() == KeyEvent.VK_RIGHT)||(e.getKeyCode() == KeyEvent.VK_D)) {
            snake.setDirection(Direction.RIGHT);
        }
        if(e.getKeyCode() == KeyEvent.VK_ENTER && gameOver) {
            resetGame();
        }
    }

         public static void main(String[] args)  {
        new PlayGame().setVisible(true);

        /**JFrame frame = new JFrame("SnakeGame");
        frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        frame.setResizable(false);

        Canvas canvas = new Canvas();
        canvas.setBackground(Color.black);
        canvas.setPreferredSize(new Dimension(GameBoard.MAP_SIZE * GameBoard.TILE_SIZE, GameBoard.MAP_SIZE * GameBoard.TILE_SIZE));

        frame.getContentPane().add(canvas);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true); 

        new Engine(canvas).startGame();*/


             }        
}

而且我还附加了 Play Button 的 actionPerformed() 方法,其中我指的是 canvas 对象

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    JFrame frame = new JFrame("SnakeGame"); 
    frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
    frame.setResizable(false);

    Canvas canvas = new Canvas();
    canvas.setBackground(Color.black);
    canvas.setPreferredSize(new Dimension(GameBoard.MAP_SIZE *GameBoard.TILE_SIZE,GameBoard.MAP_SIZE * GameBoard.TILE_SIZE));

    frame.add(canvas);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true); 

    new Engine(canvas).startGame();

    }    

所以请告诉/建议我如何将 Canvas 对象设置为焦点

最佳答案

去过那里的人的建议:

  • 您的注意力问题确实是 XY problem .
  • 相反,您不应该混合使用 AWT (Canvas) 和 Swing (JFrame) 组件,而应该坚持使用全 Swing 组件
  • 使用Key Bindings而不是 KeyListener,您的注意力问题就会消失。
  • 按照 this tutorial 在 JPanel 的 paintComponent(...) 方法中进行绘图.
  • 不要覆盖 Swing 应用程序的更新方法。

关于java - 我怎样才能将一个物体设置为焦点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19063851/

相关文章:

java - 使用本地类型推断的交叉类型的有用应用

java - 从 java netbeans 中的某些 JtextField 中删除空格

java - 避免将对象中的某些属性包含在 WSDL 中

java - 是否有一个简单的解决方案可以将列和可编辑行动态添加到 Java 中的表模型?

java - 代码以不同顺序执行,Jframe、Button 和 TextArea

java - JTextArea 未在 gui 中更新

java - 对于以下从时间戳中删除纳秒和秒组件的快速方法,是否存在任何可能失败的边缘情况?

java - 获取 JFrame 的实际当前位置

Java Swing Jbutton 访问另一个类中按下的按钮?

java - 无法更改 ActionListener 内的 JButton ActionCommand