JScrollPane doesn’t show up in JFrame

Tags: , , , ,



there. I’m writing a GUI chat client which sends message to the server and receives echoes from the server.

The top half of the client JFrame contains a JTextArea wrapped in a JScrollPane which is placed under the menubar. This JScrollPane is responsible for receiving responses from the server which receives messages from a client and broadcast it out to all clients. So, the client dedicates a seaparate thread to receiving messages.

The lower half contains a JPanel which itself contains a JTextArea and a JButton. This JPanel is responsible for receiving user’s input as message and sending it out to the server.

Now the problem is that when the client JFrame is run, the top half, that is, the JScrollPane with its JTextArea doesn’t show up on the upper half of the JFrame. Another question is that I can’t type anything in the JTextArea in the lower half although I’ve set the JTextArea editable.

Please help me crack these two myths. Thank you very much!

The code for the client is as follows:

package chatroom;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.net.*;
import java.util.*;

public class MultithreadEchoChatroomClientGUI {

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable () {
            public void run () {
                ClientFrame client = new ClientFrame();
                client.setTitle("Chat");
                client.setSize(400, 500);
                client.setVisible(true);
            }
        });
    }
}

class ClientFrame extends JFrame {
    private Socket socket;
    private Scanner input;
    private PrintWriter output;
    private JTextArea serverResponseArea;
    private JTextArea messageArea;
    private JButton sendButton;
    private static final int PORT = 1234;

    public ClientFrame () {
        initNetwork();
        initFrame();
    }

    private void initNetwork () {
        String address;
        InetAddress host = null;

        address = JOptionPane.showInputDialog("Enter the host name or IP address:");
        try {
            host = InetAddress.getByName(address);
        }
        catch (UnknownHostException uhEx) {
            JOptionPane.showMessageDialog(null, "Unknown Host!", "Error", JOptionPane.ERROR_MESSAGE);
            System.exit(1);
        }
        try {
            socket = new Socket(host, PORT);
            input = new Scanner(socket.getInputStream());

        }
        catch (IOException ioEx) {
            JOptionPane.showMessageDialog(null, ioEx.toString(), "Error", JOptionPane.ERROR_MESSAGE);
        }
        try {
            input = new Scanner(socket.getInputStream());
            output = new PrintWriter(socket.getOutputStream(), true);
        }
        catch (IOException ioEx) {
            JOptionPane.showMessageDialog(this, "Cannot create input or output stream!", "Error", JOptionPane.ERROR_MESSAGE);
            closeSocket();
            System.exit(1);
        }
    }

    private final void closeSocket () {
        try {
            socket.close();
        }
        catch (IOException ioEx) {
            JOptionPane.showMessageDialog(this, "Cannot disconnect from chatroom!", "Error", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void initFrame () {
        JMenuBar menuBar = createMenuBar();
        setJMenuBar(menuBar);

        JScrollPane responsePanel = createResponsePanel();
        add(responsePanel, BorderLayout.NORTH);

        JPanel messagePanel = createMessagePanel();
        add(messagePanel, BorderLayout.CENTER);

        addWindowListener(new WindowAdapter () {
            @Override
            public void windowClosing (WindowEvent we) {
                closeSocket();
                System.exit(0);
            }
        });
        new Thread(new Runnable () {
            public void run () {
                String clientName = null;
                String serverResponse = null;
                Scanner in = null;
                PrintWriter out = null;
                try {
                    in = new Scanner(socket.getInputStream());
                    out = new PrintWriter(socket.getOutputStream());
                }
                catch (IOException ioEx) {
                    JOptionPane.showMessageDialog(ClientFrame.this, "Cannot create input or output stream!", 
                                            "Error", JOptionPane.ERROR_MESSAGE);
                    closeSocket();
                    System.exit(1);
                }
                do {
                    clientName = JOptionPane.showInputDialog("What nickname would you like to use in the chatroom?");
                } while (clientName == null);
                out.println("#" + clientName);
                serverResponse = in.nextLine();
                serverResponseArea.append(serverResponse);
            }
        }).start();
    }

    private JMenuBar createMenuBar () {
        JMenuBar menuBar = new JMenuBar();
        JMenu menu = new JMenu("Operations");
        JMenuItem quit = new JMenuItem("Quit");
        quit.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed (ActionEvent event) {
                closeSocket();
                System.exit(0);
            }
        });
        menu.add(quit);
        menuBar.add(menu);

        return menuBar;
    }

    private JScrollPane createResponsePanel () {
        JScrollPane scrlPane = new JScrollPane();

        scrlPane.setBorder(BorderFactory.createEmptyBorder(20, 10, 10, 20));
        serverResponseArea = new JTextArea(30, 50);
        serverResponseArea.setEditable(false);
        serverResponseArea.setLineWrap(true);
        serverResponseArea.setWrapStyleWord(true);
        scrlPane.add(serverResponseArea);

        return scrlPane;
    }

    private JPanel createMessagePanel () {
        JPanel msgPanel = new JPanel();

        msgPanel.setBorder(BorderFactory.createEmptyBorder(20,10, 10, 20));
        msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.LINE_AXIS));
        JScrollPane srlPanel = createMessageTextPanel();
        msgPanel.add(srlPanel);

        JButton sdButton = createSendButton();
        msgPanel.add(sdButton);

        return msgPanel;
    }

    private JScrollPane createMessageTextPanel () {
        JScrollPane mtPanel = new JScrollPane();
        messageArea = new JTextArea(15, 35);
        messageArea.setEditable(true);
        messageArea.setLineWrap(true);
        messageArea.setWrapStyleWord(true);
        mtPanel.add(messageArea);

        return mtPanel;
    }

    private JButton createSendButton () {
        JButton button = new JButton("Send");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed (ActionEvent event) {
                String message;

                message = messageArea.getText();
                output.println(message);
                messageArea.setText(""); 
            }
        });
        return button;
    }
}

Answer

Owing to clues given by @MadProgrammer, I figured out that the problem had risen from the way I added the JTextArea to the JScrollPane. It shouldn’t have been done through scrlPane.add(serverResponseArea); but should have been done through JScrollPane scrlPane = new JScrollPane(serverResponseArea); instead.

However, since scrlPane.add(serverResponseArea); doesn’t do the trick or create any obvious visual effect, why does the compiler let it get away in the firstplace and the runtime didn’t throw such an exception? Isn’t that a bug in the design of the library? The add mehtod might have been inherited from the parent component, but if it’s ‘useless’ to the child component, why not kick it out of the child component? Maybe there is some reason for the method to continue stay there in the child component, but it can cause problems.



Source: stackoverflow