jPanel 不重绘,等待服务器消息



我正在创建一个带有套接字的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;
  }
}

最新更新