简体   繁体   中英

Can't append JTextArea

Hey Everyone I'm trying to program a client-server Tic Tac Toe game and I'm running into some problems. I'm really lost and have spent 8 hours trying to figure out what's wrong. Currently I'm trying to append a message to a JTextArea in my user interface. But it doesn't want to add anything to the text area. Any help would be greatly appreciated.

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);
    }
}

The next part is a middleman class. All messages pass through this class for manipulation.

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
    }
}

}

At first glance...

You start the program by calling...

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);
        }
    });

}

Which calls...

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

Which calls...

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;

}

Which about where it all stops...

My first thought was, "you're interacting with UI components outside of the Event Dispatching Thread", but when I back tracked the call stack, I found that you are actually stopping the Event Dispatching Thread from running altogether...

Basically. Swing is a single threaded environment, all events are processed by a single thread, known as the Event Dispatching Thread, whose job it is to, obviously, dispatch all the events coming into your application, including paint requests.

Any action that stops this thread from running (like infinite while loops and blocking I/O, lock Socket communications) will prevent it from processing any event requests, including, paint requests.

You are also required to ensure that all interactions with the UI are done from within the context of the EDT. This means you should never try and update or modify any UI component from any thread other then the EDT.

Based on what it appears you are trying to do, you best bet would be to use something like a SwingWorker .

It has the ability to execute long running tasks in the background (like Socket comms) while providing easy functionality for syncing updates back to the EDT

Take a look at Concurrency in Swing for more details

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM