我正在创建一个带有套接字的connect four游戏:一个正在运行的服务器和两个应该连接以玩游戏的客户端。我在jPanels上遇到了一些问题,这些问题由于套接字而没有更新(我想)。
当游戏(客户端)启动时,您会得到一个jPanel,其中包含IP地址的输入框和一个提交按钮。如果按下提交按钮,我想显示一条消息,说明游戏正在准备中,正在等待第二个玩家加入。
submitButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (!input.getText().equals("")) try {
prefs.put("SavedIp", input.getText());
errorLabel.setText("Preparing game and waiting for other players...");
parentLayout.startGame(input.getText());
} catch (SocketTimeoutException timeout) {
errorLabel.setText("Server timed out.");
} catch (IOException ioeException) {
errorLabel.setText("Server not found!");
} finally {
setTheCursor(Cursor.getDefaultCursor());
}
else errorLabel.setText("Enter an IP adress");
}
});
然而,在startGame方法中,会创建一个新的GamePanel,在该构造函数中会创建新的PlayField,在该PlayField中会创建带有套接字的新连接。
一旦连接,它就会运行一个方法checkForNextAction
来查看是否从服务器接收到消息。它一直运行该方法,直到服务器发送消息为止。
问题:当我按下提交时,没有看到消息显示。相反,它会挂起,直到第二个玩家加入,然后服务器发送一条消息,表示游戏可以开始,并显示游戏板。我不能立即将消息更改为我设置的文本吗?jPanel可能不会更新,因为它正在运行一个方法并等待消息
我在游戏中也遇到了类似的问题。当玩家在一列中放入一枚硬币时,这个动作会被发送到服务器,但硬币不会在jPanel上提取。相反,它挂起/冻结。另一个客户端移动,然后第一个客户端的jPanel会在第一次移动中更新硬币,并在第二次移动中使用另一个玩家的硬币。因此,似乎只有在另一名球员做出动作后,才能做出动作。
有人有主意吗?我试着使用this.revalidate()
之类的东西,但在jPanel执行startGame方法之前,我似乎无法强制他更新。
您的问题是Swing线程问题,因为等待的代码会暂停Swing事件线程,冻结所有GUI绘制和用户交互。解决方案:使用后台线程(如SwingWorker)来等待您。请查看Swing中的并发。
类似
submitButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (!input.getText().equals("")) {
prefs.put("SavedIp", input.getText());
errorLabel.setText("Preparing game and waiting for other players...");
final ParentWorker parentWorker = new ParentWorker(input.getText());
parentWorker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (SwingWorker.StateValue.DONE == evt.getNewValue()) {
setTheCursor(Cursor.getDefaultCursor());
try {
parentWorker.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
// here's where you check for your socket or io exceptions
}
}
}
});
parentWorker.execute();
// parentLayout.startGame(input.getText());
} else {
errorLabel.setText("Enter an IP adress");
}
}
});
而且。。。
class ParentWorker extends SwingWorker<Void, Void> {
private String text;
public ParentWorker(String text) {
this.text = text;
}
@Override
protected Void doInBackground() throws Exception {
parentLayout.startGame(text);
return null;
}
}