使用 Java Applet 实现键盘侦听器
Implementing Keyboard Listener with a Java Applet
我正在尝试在 Java 中创建一个简单的游戏。我正在使用 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();
}
}
所以现在,它被用于模拟,一切正常,每 3 秒进入下一回合。我想做的是使用键盘输入进入下一个回合。我希望它基本上画板,等到输入一个字符,如果字符是 "n" 然后前进一圈(基本上 运行 paint() 一次迭代然后再次等待)。
实现这个的最佳方法是什么?我尝试使用 KeyListener,但它看起来不适用于 AWT。非常感谢:)
在java中有一个名为KeyListener的接口(接口是面向对象编程中的概念)
您将 KeyListener 添加到一个对象,这里是一个示例:
https://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html
这是一个有 java 个游戏示例的网站 http://www.edu4java.com/en/game/game4.html(非常好...)
让我们开始吧,applet 正式成为一项死技术,我不会浪费时间尝试让它们发挥作用,相反,我会将您的精力集中在 API 的其他领域。有关详细信息,请参阅 Java Plugin support deprecated and Moving to a Plugin-Free Web。
您永远不应该从事件调度线程的上下文中调用 Thread.sleep
(或执行任何其他长 运行 或阻塞操作),尤其不要从绘制方法的上下文中调用。有关详细信息,请参阅 Concurrency in Java。
你永远不应该调用任何可以直接或间接生成重绘的方法,绘画是为了绘画而不是别的,这样做可能会使 EDT 饿死并导致你的程序变得无响应。
在 Swing 中制作动画的一个简单解决方案是使用 Swing Timer
,它不会阻止 EDT,但会触发它在 EDT 的内容内更新,从而可以安全地更新 UI 从内部。
有关详细信息,请参阅 How to use Swing Timers。
我还建议您看看 Painting in AWT and Swing and Performing Custom Painting,因为如果您打算进行任何类型的定制绘画,您应该对绘画过程的工作原理有所了解。
KeyListener
是一个低级别API,存在键盘焦点问题(如果它注册的组件没有键盘焦点,它不会产生事件),相反,你应该改用 Key Bindings API。
在下面的示例中,发生了两件事。这是一个正在更新 "running time" 值的 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();
}
}
}
我正在尝试在 Java 中创建一个简单的游戏。我正在使用 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();
}
}
所以现在,它被用于模拟,一切正常,每 3 秒进入下一回合。我想做的是使用键盘输入进入下一个回合。我希望它基本上画板,等到输入一个字符,如果字符是 "n" 然后前进一圈(基本上 运行 paint() 一次迭代然后再次等待)。 实现这个的最佳方法是什么?我尝试使用 KeyListener,但它看起来不适用于 AWT。非常感谢:)
在java中有一个名为KeyListener的接口(接口是面向对象编程中的概念)
您将 KeyListener 添加到一个对象,这里是一个示例:
https://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html
这是一个有 java 个游戏示例的网站 http://www.edu4java.com/en/game/game4.html(非常好...)
让我们开始吧,applet 正式成为一项死技术,我不会浪费时间尝试让它们发挥作用,相反,我会将您的精力集中在 API 的其他领域。有关详细信息,请参阅 Java Plugin support deprecated and Moving to a Plugin-Free Web。
您永远不应该从事件调度线程的上下文中调用 Thread.sleep
(或执行任何其他长 运行 或阻塞操作),尤其不要从绘制方法的上下文中调用。有关详细信息,请参阅 Concurrency in Java。
你永远不应该调用任何可以直接或间接生成重绘的方法,绘画是为了绘画而不是别的,这样做可能会使 EDT 饿死并导致你的程序变得无响应。
在 Swing 中制作动画的一个简单解决方案是使用 Swing Timer
,它不会阻止 EDT,但会触发它在 EDT 的内容内更新,从而可以安全地更新 UI 从内部。
有关详细信息,请参阅 How to use Swing Timers。
我还建议您看看 Painting in AWT and Swing and Performing Custom Painting,因为如果您打算进行任何类型的定制绘画,您应该对绘画过程的工作原理有所了解。
KeyListener
是一个低级别API,存在键盘焦点问题(如果它注册的组件没有键盘焦点,它不会产生事件),相反,你应该改用 Key Bindings API。
在下面的示例中,发生了两件事。这是一个正在更新 "running time" 值的 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();
}
}
}