用Java Applet实现键盘监听器
我想用Java创建一个简单的游戏。我使用BlueJ的IDE和我的代码,目前如下:用Java Applet实现键盘监听器
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。非常感谢你:)
让我们开始无线小应用程序正式是一种死硬的技术,我不会浪费时间让它们工作,相反,我会把你的努力集中在API的其他领域。有关更多详细信息,请参阅Java Plugin support deprecated和Moving to a Plugin-Free Web。
您不应该在事件分派线程的上下文内(或者执行任何其他长时间运行或阻塞操作)并且尤其不能从paint方法的上下文中调用Thread.sleep
。有关更多详细信息,请参阅Concurrency in Java。
您不应该调用任何可能直接或间接生成重绘的方法,绘画仅用于绘画而不用其他任何东西,否则可能会导致EDT不稳定并导致程序无响应。
在Swing中制作动画的一个简单解决方案是使用Swing Timer
,它不会阻止EDT,但会在EDT的内容中触发它的更新,从而更安全地从内部更新UI。
有关更多详细信息,请参见How to use Swing Timers。
我也建议你看看Painting in AWT and Swing和Performing Custom Painting因为如果你打算做任何类型的自定义绘画,你应该有一些了解如何绘画过程的作品。
KeyListener
是一个低级别的API,它从键盘焦点问题受到影响(如果它注册到组件没有键盘焦点,也不会产生事件),相反,你应该使用Key Bindings API来代替。
在下面的例子中,有两件事发生。该是Timer
这是更新“运行时间”值,当你按下ñ关键,它更新一个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中有这个名为的KeyListener的接口(接口意在面向对象编程的概念)
你的KeyListener添加到对象,下面是一个例子:
https://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html
这里是用java游戏的例子http://www.edu4java.com/en/game/game4.html网站(非常好... ...)
[如何使用键绑定](http://docs.oracle.co m/javase/tutorial/uiswing/misc/keybinding.html) – MadProgrammer
嗨MadProgrammer,你给的例子使用JComponent。它仍然适用于我拥有的JApplet吗?因为JApplet似乎根本不接受这个接口! –
@WassimGr这可以归结为第二点,你应该避免重写顶层容器的paint,而是使用applet作为核心组件的容器(例如,从'JComponent'或'JPanel'扩展),这样,你不要将自己锁定在一个用例中(你可以将你的核心组件添加到你喜欢的任何容器中) – MadProgrammer
[弃用Java插件的支持(http://www.gizmodo.com .au/2016/01/rest-in-hell-java-plug-in /)和[移至无插件网页](https://blogs.oracle。com/java-platform-group/entry/moving_to_a_plugin_free) – MadProgrammer
因为我知道有些人会提出这个建议,所以通常不会推荐'KeyListener',你应该看看[Key Bindings API](http://docs.oracle.com /javase/tutorial/uiswing/misc/keybinding.html),它旨在解决许多与'KeyListener'相关的问题API – MadProgrammer
不要在'paint'方法中调用'Thread.sleep',这不是应该完成动画,看看[并发中的Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/)和[如何使用Swing定时器](http://docs.oracle.com .com/javase/tutorial/uiswing/misc/timer.html)以获取更多详细信息 – MadProgrammer