2014-10-18 39 views
0

我正在創建一個連接四個遊戲與套接字:1服務器運行和兩個客戶端,應該連接玩遊戲。我對jPanels有些麻煩,因爲套接字(我認爲)沒有更新。jPanel不重繪,等待服務器消息

當遊戲(客戶端)啓動時,您會得到一個帶有IP地址輸入框和提交按鈕的jPanel。如果按下提交按鈕,我想顯示一條消息,說明遊戲正在準備中,並等待第二位玩家加入。

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被創建,並且在該構造一個新的遊戲區域被創建並在該球場一個新的連接與插座創建。

連接後,它會運行方法checkForNextAction以查看它是否從服務器接收到消息。它會一直運行該方法,直到服務器發送消息。

問題:我按提交時看不到消息。相反,它會掛起,直到第二個玩家加入,然後服務器發送一條消息,指出遊戲可以開始並顯示遊戲板。我無法立即將消息更改爲我設置的文本嗎? jPanel可能不會更新,因爲它正在運行一個方法並等待消息到來。

我在遊戲中有類似的問題。當玩家將一枚硬幣放入一列時,這一舉動被髮送到服務器,但硬幣並未在jPanel上繪製。相反,它會掛起/凍結。另一個客戶做出他的舉動,然後只有第一個客戶的jPanel得到第一步的硬幣和第二步的其他玩家的硬幣更新。所以看起來這個舉動只有在其他球員進行動作之後纔會被吸引。

有沒有人有想法?我試圖使用this.revalidate()等等,但我似乎無法強制jPanel更新,然後執行startGame方法。

回答

3

您的問題是Swing線程問題,因爲您的代碼等待,暫停Swing事件線程,凍結所有GUI繪畫和用戶交互。解決方案:使用後臺線程(例如SwingWorker)來等待您。請查看Concurrency in 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; 
    } 
} 
+0

感謝。我會盡力實施SwingWorkers! – JSS 2014-10-18 20:20:08

+0

@JSS:祝你好運! – 2014-10-18 20:25:13