点击按钮,出发处理事件,但是界面没有反应
下面是个聊天程序的客户端,我启动服务器后,我在客户端输入ip地址和端口后,点击btnNewButton_1(连接服务器)按钮,调用connect函数,发起连接服务器请求,整个界面没有反应,请大家帮忙看看问题出在哪里?
package com.myjava;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JTextArea;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.JScrollBar;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class ClientSocketFrame {
private JFrame frmChatclient;
private JTextField textIP;
private JTextField textPort;
private JTextField textField_2;
private JScrollPane scrollPane;
private JTextArea textArea;
private PrintWriter writer; // 声明PrintWriter类对象
private BufferedReader reader; // 声明BufferedReader对象
private Socket socket; // 声明Socket对象
private JButton btnNewButton_1;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ClientSocketFrame window = new ClientSocketFrame();
window.frmChatclient.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public ClientSocketFrame() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frmChatclient = new JFrame();
frmChatclient.setResizable(false);
frmChatclient.setTitle("ChatClient");
frmChatclient.setBounds(100, 100, 467, 299);
frmChatclient.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmChatclient.getContentPane().setLayout(null);
JLabel lblNewLabel = new JLabel("IP\u5730\u5740\uFF1A");
lblNewLabel.setBounds(10, 10, 60, 15);
frmChatclient.getContentPane().add(lblNewLabel);
textIP = new JTextField();
textIP.setBounds(70, 7, 131, 21);
frmChatclient.getContentPane().add(textIP);
textIP.setColumns(10);
JLabel lblNewLabel_1 = new JLabel("\u7AEF\u53E3\uFF1A");
lblNewLabel_1.setBounds(231, 10, 54, 15);
frmChatclient.getContentPane().add(lblNewLabel_1);
textPort = new JTextField();
textPort.setBounds(271, 7, 87, 21);
frmChatclient.getContentPane().add(textPort);
textPort.setColumns(10);
textField_2 = new JTextField();
textField_2.setBounds(45, 237, 325, 21);
frmChatclient.getContentPane().add(textField_2);
textField_2.setColumns(10);
JLabel lblNewLabel_2 = new JLabel(" \u6D88\u606F\uFF1A");
lblNewLabel_2.setBounds(0, 243, 54, 15);
frmChatclient.getContentPane().add(lblNewLabel_2);
JButton btnNewButton = new JButton("\u53D1\u9001");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
writer.println(textField_2.getText()); // 将文本框中信息写入流
textArea.append("客户端发送的信息是:" + textField_2.getText()
+ "\n"); // 将文本框中信息显示在文本域中
textField_2.setText(""); // 将文本框清空
}
});
btnNewButton.setBounds(376, 236, 79, 23);
frmChatclient.getContentPane().add(btnNewButton);
textArea = new JTextArea();
textArea.setBounds(10, 46, 441, 178);
frmChatclient.getContentPane().add(textArea);
btnNewButton_1 = new JButton("\u8FDE\u63A5");
btnNewButton_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
connect(textIP.getText(),Integer.parseInt(textPort.getText()));
}
});
btnNewButton_1.setBounds(368, 6, 83, 23);
frmChatclient.getContentPane().add(btnNewButton_1);
//scrollPane = new JScrollPane();
//scrollPane.setBounds(0, 227, 455, -185);
//frmChatclient.getContentPane().add(scrollPane);
// scrollPane.add(textArea);
// scrollPane.setViewportView(textArea);
}
private void connect(String ip,int port) { // 连接套接字方法
textArea.append("尝试连接......\n"); // 文本域中信息信息
try { // 捕捉异常
socket = new Socket(ip,port); // 实例化Socket对象
while (true) {
writer = new PrintWriter(socket.getOutputStream(), true);
reader = new BufferedReader(new InputStreamReader(socket
.getInputStream())); // 实例化BufferedReader对象
textArea.append("完成连接。\n"); // 文本域中提示信息
getServerInfo();
}
} catch (Exception e) {
e.printStackTrace(); // 输出异常信息
}
}
private void getServerInfo() {
try {
while (true) {
if (reader != null) {
String line = reader.readLine();// 读取服务器发送的信息
if (line != null)
textArea.append("接收到服务器发送的信息:" + line + "\n"); // 显示服务器端发送的信息
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();// 关闭流
}
if (socket != null) {
socket.close(); // 关闭套接字
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
--------------------编程问答-------------------- 补充一下,我确认了一下,点击按钮后,客户端和服务端的连接已经建立成功了,但是
textArea.append("完成连接。\n");
这行信息没有加在textArea显示出来,好像在哪里阻塞了一样。 --------------------编程问答-------------------- 经测试,在执行getServerInfo()中的
String line = reader.readLine();
时卡住了。readLine()方法一直不返回,程序一直阻塞在这里。
测试时我自己写了服务端用PrintWriter发信息,客户端用楼主的BufferedReader读信息,执行readLine()时出现问题,目前不知道什么原因,以后查查资料再说。。。
在服务端改用DataOutputStream的writeUTF()发数据,客户端用DataInputStream的readUTF()接收数据,测试成功。
至于“完成连接”显示不出来的原因,是因为程序在处理“连接”按钮的响应事件时卡在了readLine()方法处,导致按钮的响应事件无法结束,程序没有办法更新界面。
另外注意一下,connect()方法中的死循环也有问题,在里面反复不停地创建对象,不太合适吧……我盯着任务管理器,看着javaw进程的内存占用从几十M很快升到几百M,还是很壮观的。。。。。这个死循环也会使connect()方法一直执行,导致按钮响应事件无法完成,同样会使界面不能更新。getServerInfo()中的死循环也一样。在测试中我把这两个死循环都去掉了。 --------------------编程问答-------------------- 不知道“尝试连接....”这几个字显示出来没有, 我这边的结果是这几个字也没显示出来
你的这一段代码:
while (true) {
writer = new PrintWriter(socket.getOutputStream(), true);
reader = new BufferedReader(new InputStreamReader(socket
.getInputStream())); // 实例化BufferedReader对象
textArea.append("完成连接。\n"); // 文本域中提示信息
getServerInfo();
}
以及这一段代码:
while (true) {
if (reader != null) {
String line = reader.readLine();// 读取服务器发送的信息
if (line != null)
textArea.append("接收到服务器发送的信息:" + line + "\n"); // 显示服务器端发送的信息
}
}
造成了死循环,没有跳出的条件,就致使你的监听事件无法终结。
那么好了,编译器会对代码进行优化,编译器才没那么傻,它会进行编译优化,textArea.append(String)不会你调用一次就马上执行一次append操作,因为append操作只是一个信息回显的操作,而是将append的内容写入到一个缓存,到你的方法结束后一下子添加到界面中,而你的
while (true) {
writer = new PrintWriter(socket.getOutputStream(), true);
reader = new BufferedReader(new InputStreamReader(socket
.getInputStream())); // 实例化BufferedReader对象
textArea.append("完成连接。\n"); // 文本域中提示信息
getServerInfo();
}
这个循环在等待我提到的另外一个循环结束,而那个循环是个死循环,循环不能结束,造成方法也不能结束,添加到界面的机会就没有了, 也就显示不出来了
我认为你是要让客户端在那儿不停的登客户端发来的消息, 那你必须要开一个现场来等待,不然的话你什么也干不了。至于线程该怎么写, 不是一下子就能说清楚的, 好好去看看书吧 --------------------编程问答-------------------- while (true) {
writer = new PrintWriter(socket.getOutputStream(), true);
reader = new BufferedReader(new InputStreamReader(socket
.getInputStream())); // 实例化BufferedReader对象
textArea.append("完成连接。\n"); // 文本域中提示信息
getServerInfo();
}
连接不需要写死循环。
while (true) {
if (reader != null) {
String line = reader.readLine();// 读取服务器发送的信息
if (line != null)
textArea.append("接收到服务器发送的信息:" + line + "\n"); // 显示服务器端发送的信息
}
}
像这种需要等待的死循环都需要用线程处理,如果你用线程,你服务器不返回消息,你这个程序就是阻塞开始状态。 --------------------编程问答-------------------- 返回链接完成 提示后,将界面重绘一下,或者刷新一下,就会显示出来了 --------------------编程问答-------------------- 前面的同学说死循环的问题:
我点了按钮应该在循环之前先执行textArea.append("尝试连接......\n");
这句为什么也显示不出来呢,有个同学说刷新或重绘界面这个怎么做呢。
的确是在哪里卡住了,我如果关闭掉服务端,客户端就会把这些信息显示出来了。 --------------------编程问答--------------------
不是刷新和重绘的问题 --------------------编程问答--------------------