JScrollPane不在JFrame中显示

问题描述 投票:0回答:1

有。我正在编写一个GUI聊天客户端,该客户端将消息发送到服务器并接收来自服务器的回声。

客户端JFrame的上半部分包含一个JTextArea,该JTextArea包装在JScrollPane中,该JScrollPane置于菜单栏下方。此JScrollPane负责从服务器接收响应,该服务器从客户端接收消息并将其广播给所有客户端。因此,客户端将专用线程用于接收消息。

下半部分包含一个JPanel,它本身包含一个JTextArea和一个JButton。此JPanel负责接收用户输入的消息,并将其发送到服务器。

现在的问题是,当运行客户端JFrame时,上半部分(即带有JTextArea的JScrollPane)不会显示在JFrame的上半部分。另一个问题是,尽管我已将JTextArea设置为可编辑的,但我不能在下半部分的JTextArea中键入任何内容。

[请帮助我破解这两个神话。非常感谢!

客户端代码如下:

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;
    }
}
java swing jframe jscrollpane jtextarea
1个回答
0
投票

由于@MadProgrammer提供的线索,我发现问题出在我将JTextArea添加到JScrollPane的方式中。它不应该通过scrlPane.add(serverResponseArea);完成,而应该通过JScrollPane scrlPane = new JScrollPane(serverResponseArea);完成。

但是,由于scrlPane.add(serverResponseArea);并不能解决问题,也不产生任何明显的视觉效果,为什么编译器首先让它脱颖而出,而运行时没有抛出此类异常?这不是库设计中的错误吗? add方法可能是从父组件继承的,但是如果对子组件“无用”,为什么不将其踢出子组件呢?也许由于某种原因该方法继续停留在子组件中,但可能会导致问题。

© www.soinside.com 2019 - 2024. All rights reserved.