我正在用Java制作一个简单的基于文本的基于回合的战斗游戏(作为一个学习练习,所以我试图理解我所做的每一件事),并且我想模拟对手的转弯。这实质上涉及打印一条消息(例如:“敌人的回合”),处理敌人的回合,暂停(与Thread.sleep
),然后打印出另一条消息(例如“你的回合”)。
我的GUI是一个带有Swing元素的JApplet
类,尽管这是因为它很容易制作和理解,而不是因为我对使用Swing有任何依附。我没有多线程方面的经验,但我读过SwingWorker
在这种情况下很有用(在运行冗长的后台进程时更新Swing GUI )。以下是一个没有实际游戏代码的版本,为了简单起见,所有代码都包含在同一个类中:
public class SimpleGame extends JApplet implements ActionListener {
private Game game;
private String inputCommand;
private JTextArea textOutput;
private JTextField inputField;
public void init() {
textOutput = new JTextArea();
DefaultCaret caret = (DefaultCaret) textOutput.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
textOutput.setEditable(false);
Container window = getContentPane();
window.setLayout(new BorderLayout());
window.add(textOutput, BorderLayout.CENTER);
JButton submitButton = new JButton("Submit");
submitButton.addActionListener(this);
inputField = new JTextField(20);
inputField.addActionListener(this);
JPanel inputPanel = new JPanel();
inputPanel.add(inputField);
inputPanel.add(submitButton);
window.add(inputPanel, BorderLayout.SOUTH);
inputField.requestFocusInWindow();
game = new Game();
}
public class GuiUpdater extends SwingWorker<Boolean, String> {
private String command;
public GuiUpdater(String inputCommand) {
super();
command = inputCommand;
}
public void publish(String chunk) {
super.publish(chunk);
}
protected Boolean doInBackground() throws Exception {
Output.setWorker(this);
boolean successfulCommand = game.performCommand(command);
return successfulCommand;
}
protected void process(List<String> chunks) {
for (String chunk : chunks) {
textOutput.append(chunk);
}
}
}
public void actionPerformed(ActionEvent event) {
if (game.isItYourTurn()) {
inputCommand = inputField.getText();
if (inputCommand.length() != 0) {
GuiUpdater worker = new GuiUpdater(inputCommand);
worker.execute();
boolean successfulCommand;
try {
successfulCommand = worker.get();
} catch (InterruptedException | ExecutionException e) {
successfulCommand = false;
}
if (!successfulCommand) {
textOutput.append("Invalid command.\n");
}
inputField.setText("");
}
} else {
textOutput.append("\nWait for your turn!\n");
}
}
private static class Output {
private static GuiUpdater worker;
static void setWorker(GuiUpdater newWorker) {
worker = newWorker;
}
static void update(String updateText) {
worker.publish(updateText);
}
}
private class Game {
private boolean yourTurn;
public Game() {
yourTurn = true;
}
public boolean isItYourTurn() {
return yourTurn;
}
public boolean performCommand(String inputString) throws InterruptedException {
yourTurn = false;
// perform player action
Output.update("\nEnemy turn");
Thread.sleep(1000);
// perform enemy action
Output.update("\nYour turn");
yourTurn = true;
return true;
}
}
}
不幸的是,没有输出一行,等待第二行,然后输出第二行,所有行都在所有睡眠完成后输出到Swing GUI。如果我将Output.update("text")
替换为System.out.println("text")
,那么计时就会像预期的那样工作,但显然我不想只依赖于游戏的控制台输出。
如果有人对我做错了什么有解释,或者有一种在输出之间暂停的替代方法,我们将不胜感激。干杯!
发布于 2014-10-22 20:39:10
对worker.get()的调用会阻塞swing-applet线程,直到工作人员完成为止。您需要将结果的处理移到SwingWorker done()方法中,在doInBackground()方法完成之前不会执行该方法。代码的这一部分应该如下所示:
public class GuiUpdater extends SwingWorker<Boolean, String> {
private String command;
public GuiUpdater(String inputCommand) {
super();
command = inputCommand;
}
public void publish(String chunk) {
super.publish(chunk);
}
@Override
protected Boolean doInBackground() throws Exception {
Output.setWorker(this);
boolean successfulCommand = game.performCommand(command);
return successfulCommand;
}
@Override
protected void process(List<String> chunks) {
for (String chunk : chunks) {
textOutput.append(chunk);
}
}
@Override
protected void done() {
boolean successfulCommand;
try {
successfulCommand = get();
} catch (InterruptedException | ExecutionException e) {
successfulCommand = false;
}
if (!successfulCommand) {
textOutput.append("Invalid command.\n");
}
inputField.setText("");
}
}
@Override
public void actionPerformed(ActionEvent event) {
if (game.isItYourTurn()) {
inputCommand = inputField.getText();
if (inputCommand.length() != 0) {
GuiUpdater worker = new GuiUpdater(inputCommand);
worker.execute();
}
} else {
textOutput.append("\nWait for your turn!\n");
}
}
https://stackoverflow.com/questions/26476465
复制