2013-11-26 113 views
0

嘿每個人我試圖編寫一個客戶端服務器井字遊戲,我遇到了一些問題。我真的迷失了,花了8個小時試圖弄清楚什麼是錯的。目前我正在嘗試在我的用戶界面中向JTextArea附加消息。但它不想在文本區域添加任何內容。任何幫助將不勝感激。不能附加JTextArea

public class GameUI extends javax.swing.JFrame{ 
    /** 
    * The circle icon 
    */ 
    private ImageIcon circle = new ImageIcon("data/tile-05.png"); 

    /** 
    * The cross icon 
    */ 
    private ImageIcon cross = new ImageIcon("data/tile-03.png"); 

    /** 
    * keeps track of whose turn it is 
    */ 
    private int turn = 1; 

    /** 
    * Where the hear of the game runs 
    */ 
    private Client game; 

    /** 
    * This is an 2d array that stores all the buttons 
    */ 
    JButton[][] buttons = new JButton[3][3]; 

    /** 
    * Class constructor Creates new form GameUI 
    */ 
    public GameUI() { 
     startGame("Tic Tac"); 
     storeButtons(); 
    } 

    public void connectionError(String message) { 
     JOptionPane.showMessageDialog(rootPane, message, "Tic Tac Toe", 0); 
    } 

    private void startGame(String message) { 
     String host, login; 
     int temp = 0; 

     JTextField hostText = new JTextField(); 
     JTextField loginText = new JTextField(); 

     Object[] info = {"Host: ", hostText, "login ID: ", loginText}; 

     temp = JOptionPane.showConfirmDialog(rootPane, info, message, JOptionPane.OK_CANCEL_OPTION); 

     while (true) { 
      try { 
       if (temp == JOptionPane.OK_OPTION) { 
        host = hostText.getText(); 
        login = loginText.getText(); 

        game = new Client(login, host, 5555, this); //Initializes the game 
        initComponents(); 
        break; 
       } else if (temp == JOptionPane.CANCEL_OPTION || temp == JOptionPane.CLOSED_OPTION) { 
        System.exit(0); 
       } 
      } catch (IOException e2) { 
       connectionError("Can't connect to the game server!"); 
       System.exit(0); 
      } 
     } 
     //Scrubs memory for more RAM :) 
     login = null; 
     host = null; 

    } 

    private void storeButtons() { 
     buttons[0][0] = btnTicTac1; 
     buttons[0][1] = btnTicTac2; 
     buttons[0][2] = btnTicTac3; 
     buttons[1][0] = btnTicTac4; 
     buttons[1][1] = btnTicTac5; 
     buttons[1][2] = btnTicTac6; 
     buttons[2][0] = btnTicTac7; 
     buttons[2][1] = btnTicTac8; 
     buttons[2][2] = btnTicTac9; 
    } 

    private void btnOpponentSendActionPerformed(java.awt.event.ActionEvent evt) {             
     String message = txtOpponentMessage.getText(); 
     game.handleMessageFromGameUI("#Opponent " + message); //Specified the game text area 
     txtOpponentMessage.setText(""); 
    }            

    private void btnLobbySendActionPerformed(java.awt.event.ActionEvent evt) {            
     String message = txtLobbyMessage.getText(); 
     game.handleMessageFromGameUI("#lobby " + message); //Specified the lobby text area 
     txtLobbyMessage.setText(""); 
    }             

    public void setTurn(int value) { 
     turn = value; 
    } 

    public void appendLobbyArea(String message) { 
     txtLobbyTextArea.append(message); 
    } 

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String args[]) { 
     /* Create and display the form */ 
     java.awt.EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 

       GameUI cgui = new GameUI(); 
       cgui.setVisible(true); 
      } 
     }); 

    } 

    // Variables declaration - do not modify      
    private javax.swing.JButton btnLobbySend; 
    private javax.swing.JButton btnOpponentSend; 
    private javax.swing.JButton btnTicTac1; 
    private javax.swing.JButton btnTicTac2; 
    private javax.swing.JButton btnTicTac3; 
    private javax.swing.JButton btnTicTac4; 
    private javax.swing.JButton btnTicTac5; 
    private javax.swing.JButton btnTicTac6; 
    private javax.swing.JButton btnTicTac7; 
    private javax.swing.JButton btnTicTac8; 
    private javax.swing.JButton btnTicTac9; 
    private javax.swing.JComboBox jComboBox1; 
    private javax.swing.JLabel jLabel1; 
    private javax.swing.JLabel jLabel2; 
    private javax.swing.JLabel jLabel3; 
    private javax.swing.JScrollPane jScrollPane1; 
    private javax.swing.JScrollPane jScrollPane2; 
    private javax.swing.JScrollPane jScrollPane4; 
    private javax.swing.JLabel lblOpponentSelect; 
    private javax.swing.JList txtClientList; 
    private javax.swing.JTextArea txtGameTextArea; 
    private javax.swing.JTextField txtLobbyMessage; 
    private javax.swing.JTextArea txtLobbyTextArea; 
    private javax.swing.JTextField txtOpponentMessage; 
    // End of variables declaration     

    public void display(String message) { 
     System.out.println(message); 
    } 
} 

下一部分是中間人類。所有消息都通過這個類進行操作。

public class Client extends AbstractClient { 

/** 
* GameUI Object. Used to communicate from the game to the end user 
*/ 
private GameUI gameUI; 

/** 
* This keeps track of whose turn it is. Defaults to x. 
*/ 
private int turn = 1; 

public Client(String userID, String host, int port, GameUI gameUI) throws IOException { 
    super(host, port); 
    this.gameUI = gameUI; 
    openConnection(); 
    sendToServer("#login " + "<" + userID + ">"); 
} 

@Override 
public void handleMessageFromServer(Object msg) { 
    while (isConnected()) { 
     if (msg.toString().startsWith("#")) { 
      doFunction(msg); 
     } else { 

     } 
    } 
} 

public void handleMessageFromGameUI(String message) { 
    try { 
    sendToServer(message); 
    } catch (IOException e) { 
     gameUI.display("Can't send message to server"); 
     System.exit(0); 
    } 
} 

private void doFunction(Object msg) { 
    if (msg.toString().startsWith("#connectedClient")) { 
     gameUI.appendLobbyArea(msg.toString().substring(17) + " connected"); 
    } else if (msg.toString().startsWith("#disconnectedClient")) { 
     gameUI.appendLobbyArea(msg.toString().substring(20) + " disconnected"); 
    } else if (msg.toString().startsWith("#lobby")) { 
     gameUI.appendLobbyArea(msg.toString().substring(7)); //Add client username 
    } 
} 

}

+0

爲了更好的幫助的能力更快,發佈[SSCCE](http://sscce.org/)。 –

回答

1

乍一看...

您可以通過調用啓動程序...

public static void main(String args[]) { 
    /* Create and display the form */ 
    java.awt.EventQueue.invokeLater(new Runnable() { 
     @Override 
     public void run() { 

      GameUI cgui = new GameUI(); 
      cgui.setVisible(true); 
     } 
    }); 

} 

其中要求...

public GameUI() { 
    startGame("Tic Tac"); 
    storeButtons(); 
} 

哪個電話...

private void startGame(String message) { 
    String host, login; 
    int temp = 0; 

    JTextField hostText = new JTextField(); 
    JTextField loginText = new JTextField(); 

    Object[] info = {"Host: ", hostText, "login ID: ", loginText}; 

    temp = JOptionPane.showConfirmDialog(rootPane, info, message, JOptionPane.OK_CANCEL_OPTION); 

    while (true) { 
     try { 
      if (temp == JOptionPane.OK_OPTION) { 
       host = hostText.getText(); 
       login = loginText.getText(); 

       game = new Client(login, host, 5555, this); //Initializes the game 
       initComponents(); 
       break; 
      } else if (temp == JOptionPane.CANCEL_OPTION || temp == JOptionPane.CLOSED_OPTION) { 
       System.exit(0); 
      } 
     } catch (IOException e2) { 
      connectionError("Can't connect to the game server!"); 
      System.exit(0); 
     } 
    } 
    //Scrubs memory for more RAM :) 
    login = null; 
    host = null; 

} 

其中大約在這一切停止......

我的第一個念頭是,「你與事件指派線程之外的UI組件交互」,但是當我回到跟蹤調用堆棧,我發現你實際上是停止事件調度線程從運行...

基本上。 Swing是一個單線程環境,所有事件都由一個稱爲Event Dispatching Thread的線程處理,它的工作顯然是派遣所有進入應用程序的事件,包括繪畫請求。

阻止此線程運行的任何操作(如無限循環和阻塞I/O,鎖Socket通信)將阻止它處理任何事件請求,包括繪製請求。

您還需要確保所有與UI的交互都是在EDT的背景下完成的。這意味着您不應該嘗試更新或修改EDT之外的任何線程中的任何UI組件。

根據看起來你正在嘗試做什麼,你最好打賭會使用像SwingWorker

它在後臺執行長時間運行的任務(如Socket通訊)而同步更新回EDT

提供方便的功能,看看Concurrency in Swing更多細節

+0

好吧,如果我理解正確,我必須爲我的startGame(String message)方法使用SwingWorker,以便EDT可以繼續運行而不會被我的while(true)循環中斷? –

+0

您還需要更改程序的運行方式,因爲您不應該對EDT之外的用戶界面進行修改。這意味着,你不能簡單地將'startGame'的內容移動到'SwingWorker'中,因爲它只會產生更多的問題。您需要考慮如何彌合線程('SwingWorker')和UI之間的差距 – MadProgrammer

+0

+1我在這裏沒有看到多長時間CANCEL_OPTION/CLOSED_OPTION – mKorbel