简体   繁体   English

JScrollPane 没有出现在 JFrame

[英]JScrollPane doesn't show up in JFrame

there.那里。 I'm writing a GUI chat client which sends message to the server and receives echoes from the server.我正在编写一个 GUI 聊天客户端,它将消息发送到服务器并从服务器接收回声。

The top half of the client JFrame contains a JTextArea wrapped in a JScrollPane which is placed under the menubar.客户端 JFrame 的上半部分包含一个包裹在 JScrollPane 中的 JTextArea,该 JScrollPane 位于菜单栏下方。 This JScrollPane is responsible for receiving responses from the server which receives messages from a client and broadcast it out to all clients.此 JScrollPane 负责接收来自服务器的响应,该服务器接收来自客户端的消息并将其广播给所有客户端。 So, the client dedicates a seaparate thread to receiving messages.因此,客户端专用一个单独的线程来接收消息。

The lower half contains a JPanel which itself contains a JTextArea and a JButton.下半部分包含一个 JPanel,它本身包含一个 JTextArea 和一个 JButton。 This JPanel is responsible for receiving user's input as message and sending it out to the server.这个 JPanel 负责接收用户的输入作为消息并将其发送到服务器。

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.现在的问题是,当客户端 JFrame 运行时,上半部分,即带有 JTextArea 的 JScrollPane 不会出现在 JFrame 的上半部分。 Another question is that I can't type anything in the JTextArea in the lower half although I've set the JTextArea editable.另一个问题是,尽管我已将 JTextArea 设置为可编辑,但我无法在下半部分的 JTextArea 中键入任何内容。

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

Owing to clues given by @MadProgrammer, I figured out that the problem had risen from the way I added the JTextArea to the JScrollPane.由于@MadProgrammer 提供的线索,我发现问题源于我将 JTextArea 添加到 JScrollPane 的方式。 It shouldn't have been done through scrlPane.add(serverResponseArea);不应该通过scrlPane.add(serverResponseArea); but should have been done through JScrollPane scrlPane = new JScrollPane(serverResponseArea);但应该通过JScrollPane scrlPane = new JScrollPane(serverResponseArea); instead.反而。

However, since scrlPane.add(serverResponseArea);但是,由于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? add方法可能是从父组件继承的,但如果它对子组件“无用”,为什么不将它踢出子组件呢? Maybe there is some reason for the method to continue stay there in the child component, but it can cause problems.也许有一些原因使该方法继续留在子组件中,但这可能会导致问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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