简体   繁体   English

使用Java Applet实现键盘侦听器

[英]Implementing Keyboard Listener with a Java Applet

I am trying to create a simple game in Java. 我正在尝试用Java创建一个简单的游戏。 I am using BlueJ IDE and my code is currently as follows : 我正在使用BlueJ IDE,目前的代码如下:

import java.util.*;
import java.awt.*;
import javax.swing.*;    

public class GameGraphic extends JApplet
{

    // Variable initialization
    private Board board;
    private Dice dice;
    private ArrayList<Player> players; 
    private Player currentPlayer;

    // etc..

    public void init()
    {
        setSize(600,800);

        // Code to initialize game, load images
        // etc..

    }

    // Game method etc..

    public void paint(Graphics g)
    {
        // Drawing game board etc..

        turn++;
        int diceRoll = dice.roll();


        advancePlayer(currentPlayer, steps);
        changeCoins(currentPlayer, diceRoll);

        whoseTurn = (whoseTurn+1)%players.size();

        while(command=="w") {
        }

        try {
        Thread.sleep(3000);
        } catch(InterruptedException ex) {
        Thread.currentThread().interrupt();
        } 

        revalidate();
        repaint();
    }
}

So right now, it is used a simulation, everything works well and it goes to the next turn each 3 seconds. 因此,现在使用它进行模拟,一切运行良好,每3秒钟转到下一轮。 What I want to do is use keyboard input to go to the next turn. 我想做的是使用键盘输入转到下一轮。 I want it to basically draw the board, wait until a character is typed, if the character is "n" then advance one turn (basically run paint() for one iteration and wait again). 我希望它基本上画板,等到键入一个字符为止,如果字符为“ n”,则前进一圈(基本上运行paint()进行一次迭代,然后再次等待)。 What is the best way to implement this? 实现此目的的最佳方法是什么? I tried using KeyListener but it looks like it does not work with AWT. 我尝试使用KeyListener,但它似乎不适用于AWT。 Thank you so much :) 非常感谢 :)

Let's start with, applets are officially a dead technology and I wouldn't waste time trying to make them work, instead, I'd focus your efforts in other areas of the API. 让我们开始吧,applet正式是一种过时的技术,我不会浪费时间尝试使它们起作用,相反,我会将精力集中在API的其他领域。 See Java Plugin support deprecated and Moving to a Plugin-Free Web for more details. 有关更多详细信息,请参阅不建议使用Java插件支持移至无插件Web

You should never call Thread.sleep from within the context of the Event Dispatching Thread (or perform any other long running or blocking operations) and especially not from within the context of a paint method. 永远不要从“事件调度线程”的上下文中调用Thread.sleep (或执行任何其他长时间运行或阻止的操作),尤其是不要从paint方法的上下文中调用Thread.sleep See Concurrency in Java for more details. 有关更多详细信息,请参见Java中的并发

You should never call any method which could generate a repaint directly or indirectly, painting is for painting and nothing else, doing so could starve the EDT and cause your program to become unresponsive. 您永远不要调用任何可能直接或间接生成重画的方法,绘画是用于绘画的,别无其他,这样做可能会使EDT饿死并使程序变得无响应。

A simple solution to doing animation in Swing is to use a Swing Timer , which won't block the EDT but which triggers it updates within the content of the EDT, making it safe to update the UI from within. 在Swing中制作动画的一个简单解决方案是使用Swing Timer ,它不会阻止EDT,但会触发它在EDT内容内进行更新,从而可以安全地从内部更新UI。

See How to use Swing Timers for more details. 有关更多详细信息,请参见如何使用Swing计时器

I'd also recommend you have a look at Painting in AWT and Swing and Performing Custom Painting because if you intend to do any kind of custom painting, you should have some understand of how the painting process works. 我还建议您看一下AWT中的绘画以及“摇摆执行自定义绘画”,因为如果您打算进行任何类型的自定义绘画,您应该对绘画过程的工作原理有所了解。

KeyListener is a low level API, which suffers from keyboard focus issues (if the component it's registered to does not have keyboard focus, it won't generate events), instead, you should be using the Key Bindings API instead. KeyListener是一个低级API,它会遇到键盘焦点问题(如果注册的组件没有键盘焦点,则不会生成事件),相反,您应该改用Key Bindings API。

In the following example, there are two things happening. 在下面的示例中,发生了两件事。 The is a Timer which is updating a "running time" value and when you press the N key, it updates a turn variable 是一个Timer ,它正在更新“运行时间”值,当您按N键时,它将更新turn变量

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class GameGraphic  {

    public static void main(String[] args) {
        new GameGraphic();
    }

    public GameGraphic() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new GamePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class GamePane extends JPanel {
        private int turn = 0;
        private long runtime;

        public GamePane() {
            InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap actionMap = getActionMap();

            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_N, 0), "next");
            actionMap.put("next", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println("...");
                    turn++;
                    repaint();
                }
            });

            long startTime = System.currentTimeMillis();
            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    runtime = System.currentTimeMillis() - startTime;
                    repaint();
                }
            });
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g); 
            Graphics2D g2d = (Graphics2D) g.create();
            int width = getWidth();
            int height = getHeight();
            FontMetrics fm = g2d.getFontMetrics();
            String text = Integer.toString(turn);
            int x = (width - fm.stringWidth(text)) / 2;
            int y = ((height - fm.getHeight()) / 2) + fm.getAscent();
            g2d.drawString(text, x, y);

            text = Long.toString(runtime);
            x = width - fm.stringWidth(text);
            y = height - fm.getHeight() + fm.getAscent();
            g2d.drawString(text, x, y);
            g2d.dispose();
        }


    }
}

In java there is an interface for this named KeyListener (interface meaning the concept in object-oriented programming) 在Java中,有一个名为KeyListener的接口(该接口表示面向对象编程中的概念)

you add the KeyListener to an object, here is an example: 您将KeyListener添加到对象,这是一个示例:

https://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html https://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html

here is a website with java game examples http://www.edu4java.com/en/game/game4.html (very good...) 这是一个带有Java游戏示例的网站, 网址为http://www.edu4java.com/en/game/game4.html (非常好...)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM