2013-11-26 44 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