聊天程序会冻结JFrame

时间:2013-05-23 15:37:26

标签: java swing awt jlist event-dispatch-thread

我正在编写一个简单的聊天客户端,并将其移动到一个漂亮的GUI。服务器端的构造函数(客户端是android)包含一个在JFrame中的列表,服务器的第一部分运行,但随后整个框架锁定。有谁看到这个问题?对不起,相对杂乱无章的评论代码...... 服务器:

    import java.awt.List;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;


public class ChatServer {

    private final int CHAT_PORT = 4453;
    ServerSocket sSocket;
    Socket cSocket;
    PrintWriter pWriter;
    BufferedReader bReader;
    InetAddress localAddr;
    List messageList;

    public ChatServer(List entList)
    {
        messageList = entList;
    }

    public synchronized void run()
    {
        messageList.add("Chat Server Starting...");
        try {
            localAddr = InetAddress.getLocalHost();
        } catch (UnknownHostException e1) {
            messageList.add("InnetAddress error");
        }
        while(true)
        {
            try {
                sSocket = new ServerSocket(CHAT_PORT);
                sSocket.setReuseAddress(true);
                messageList.add("Server has IP:" + localAddr.getHostAddress());
                messageList.add("Server has hostname:" + localAddr.getHostName());
                messageList.add("Server has port:" + CHAT_PORT);
            } catch (IOException e) {
                //ERRORS
                if(cSocket.isConnected())
                {
                    messageList.add("User disconnected\n");
                    try {
                        cSocket.close();
                    } catch (IOException e1) {
                        messageList.add("Error closing client socket");
                    }
                }
                else
                {
                    messageList.add("ERROR CREATING SOCKET\n");
                }
            }

            try {
                cSocket = sSocket.accept();
                cSocket.setReuseAddress(true);
                messageList.add("INFO: socket connected");
            } catch (IOException e) {
                messageList.add("Client Socket Error");
                System.exit(-1);
            }

            try {
                pWriter = new PrintWriter(cSocket.getOutputStream(), true);
                messageList.add("INFO: Print writer opened");
            } catch (IOException e) {
                messageList.add("PrintWriter error");
            }

            try {
                bReader = new BufferedReader(new InputStreamReader(cSocket.getInputStream()));
                messageList.add("INFO: buffered reader opened");
            } catch (IOException e) {
                messageList.add("BufferedReader error");
            }

            String inputLine;

            try {
                while((inputLine = bReader.readLine()) != null)
                {
                    messageList.add(inputLine);
                    if(inputLine.equals("close"))
                    {
                        close();
                    }
                }
            } catch (IOException e) {
                messageList.add("Buffered Reader error");
            }
        }

    }


    public synchronized void close()
    {
        messageList.add("****Server closing****");
        try {
            sSocket.close();
        } catch (IOException e) {
            messageList.add("Error closing server socket");
        }

        try {
            cSocket.close();
        } catch (IOException e) {
            messageList.add("Error closing client socket");
        }

        pWriter.close();


        try {
            bReader.close();
        } catch (IOException e) {
            messageList.add("Error closing buffered reader");
        }
        messageList.add("****It's been fun, but I've got to go.****\n****Server has shut down.****");
        System.exit(0);
    }

}

GUI:

    import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JMenu;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.List;
import java.awt.Toolkit;


@SuppressWarnings("serial")
public class ClientGUI extends JFrame {

    private JPanel contentPane;
    private JTextField txtEnterTextHere;
    private JMenuBar menuBar;
    private List messageList;
    private JMenu mnOptions;
    private JMenu mnHelp;
    private JMenuItem mntmStartServer;
    private JMenuItem mntmStopServer;
    private JMenuItem mntmConnectionInfo;
    private JMenuItem mntmEmailDeveloper;
    private static String userName;
    private ChatServer cServer;


    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    ClientGUI frame = new ClientGUI();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public ClientGUI() {
        setTitle("Ben's Chat Client");
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);

        menuBar = new JMenuBar();
        setJMenuBar(menuBar);

        JMenu mnFile = new JMenu("File");
        menuBar.add(mnFile);

        JMenuItem mntmExit = new JMenuItem("Exit");
        mntmExit.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                JOptionPane.showConfirmDialog(null, "Are you sure you want to exit?");
            }



        });
        mnFile.add(mntmExit);

        mnOptions = new JMenu("Options");
        menuBar.add(mnOptions);

        mntmStartServer = new JMenuItem("Start Server");
        mntmStartServer.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                ChatServer cServer = new ChatServer(messageList);   
                cServer.run();
            }
        });
        mnOptions.add(mntmStartServer);

        mntmStopServer = new JMenuItem("Stop Server");
        mnOptions.add(mntmStopServer);

        mntmConnectionInfo = new JMenuItem("Connection Info");
        mnOptions.add(mntmConnectionInfo);

        mnHelp = new JMenu("Help");
        menuBar.add(mnHelp);

        mntmEmailDeveloper = new JMenuItem("Email Developer");
        mnHelp.add(mntmEmailDeveloper);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        txtEnterTextHere = new JTextField();
        txtEnterTextHere.setBounds(10, 220, 334, 20);
        txtEnterTextHere.setText("Enter text here...");
        contentPane.add(txtEnterTextHere);
        txtEnterTextHere.setColumns(10);

        JButton btnSend = new JButton("Send");
        btnSend.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                messageList.add(userName + ": " + txtEnterTextHere.getText().toString());
            }
        });

        messageList = new List();   
        btnSend.setBounds(349, 219, 85, 23);
        contentPane.add(btnSend);
        messageList.setBounds(10, 10, 424, 204);
        contentPane.add(messageList);

    }

    public static String getUsername()
    {
        return userName;
    }

    public static void setUsername(String entName)
    {
        userName = entName;
    }
}

谢谢!

1 个答案:

答案 0 :(得分:2)

看起来您正在Swing线程上启动服务器(请参阅:The Event Dispatch Thread)。只要您在cServer.run();中拨打ActionListener,就会阻止EDT执行任何其他操作(例如更新JFrame并回复事件)。改为在后台线程中启动服务器:

new Thread(new Runnable()
{
  @Override
  public void run()
  {
    // start your server
  }
}).start();