我正在尝试用 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。非常感谢你:)
最佳答案
首先,小程序正式成为一种死技术,我不会浪费时间尝试让它们发挥作用,相反,我会将您的精力集中在 API 的其他领域。请参阅Java Plugin support deprecated和 Moving to a Plugin-Free Web了解更多详情。
您永远不应该从事件调度线程的上下文中调用 Thread.sleep(或执行任何其他长时间运行或阻塞操作),尤其不要从绘制方法的上下文中调用。请参阅Concurrency in Java了解更多详情。
你永远不应该调用任何可以直接或间接生成重绘的方法,绘画只是为了绘画而没有别的,这样做可能会导致 EDT 饥饿并导致你的程序变得无响应。
在 Swing 中制作动画的一个简单解决方案是使用 Swing Timer
,它不会阻止 EDT,但会触发 EDT 内容内的更新,从而可以安全地更新来自内部的用户界面。
参见How to use Swing Timers了解更多详情。
我还建议您看看Painting in AWT and Swing和 Performing Custom Painting因为如果您打算进行任何类型的自定义绘画,您应该对绘画过程的工作原理有一定的了解。
KeyListener
是一个低级 API,它存在键盘焦点问题(如果它注册的组件没有键盘焦点,它不会生成事件),相反,您应该使用Key Bindings API 代替。
在下面的示例中,发生了两件事。这是一个定时器
,它正在更新“运行时间”值,当您按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 - 使用 Java Applet 实现键盘监听器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35688860/