package chatprogram;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import com.sun.xml.internal.messaging.saaj.soap.ver1_1.Envelope1_1Impl;
import com.sun.xml.internal.ws.wsdl.writer.document.Port;
import jdk.nashorn.internal.scripts.JO;
import sun.net.InetAddressCachePolicy;
public class GuiChat extends JFrame{
private static final int DEFAULT_PORT=16530;
//把主窗口分为north center south三个部分
private JLabel stateLB;//显示监听状态
private JTextArea centerTextArea;//显示聊天记录
private JPanel southPanel;//最下边的面板
private JTextArea inputTextArea;//聊天输入框
private JPanel bottomPanel;//放置IP输入框 按钮等
private JTextField ipTextField;//ip输入框
private JTextField remotePortTF;//端口号输入框
private JButton sendBT;//发送按钮
private JButton clearBT;//清楚聊天记录按钮
private DatagramSocket datagramSocket;//用于后边功能的实现
//定义一个setUpUI方法,实现用户图形界面的设置
private void setUpUI(){
setTitle("GUI聊天");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400,400);//设置窗口大小
setLocationRelativeTo(null);//窗口居中
setResizable(false);//设置窗口大小不可调整
//设置north部分
stateLB=new JLabel("当前还未启动监听");
stateLB.setHorizontalAlignment(JLabel.RIGHT);
//设置center部分
centerTextArea=new JTextArea();//聊天记录显示区域
centerTextArea.setEditable(false);
centerTextArea.setBackground(new Color(211,211,211));
//设置south部分
southPanel=new JPanel(new BorderLayout());
inputTextArea=new JTextArea(5,20);//内容输入区域
bottomPanel=new JPanel(new FlowLayout(FlowLayout.CENTER,5,5));
ipTextField=new JTextField("127.0.0.1",8);
remotePortTF=new JTextField(String.valueOf(DEFAULT_PORT),3);
sendBT=new JButton("发送");
clearBT=new JButton("清屏");
bottomPanel.add(ipTextField);
bottomPanel.add(remotePortTF);
bottomPanel.add(sendBT);
bottomPanel.add(clearBT);
southPanel.add(new JScrollPane(inputTextArea),BorderLayout.CENTER);
southPanel.add(bottomPanel,BorderLayout.SOUTH);
//添加窗口north center south部分组件
add(stateLB,BorderLayout.NORTH);
add(new JScrollPane(centerTextArea),BorderLayout.CENTER);
add(southPanel,BorderLayout.SOUTH);
setVisible(true);
}
//给按钮添加监听事件,sendBT clearBT按钮的监听事件封装在setListener方法中
private void setListener(){
sendBT.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO 自动生成的方法存根
//获取发送的目标IP地址和端口号
final String ipAddresString=ipTextField.getText();
final String remotePort=remotePortTF.getText();
//判断IP地址和端口号是否为空
if(ipAddresString==null||ipAddresString.trim().equals("")||remotePort==null||remotePort.trim().equals("")){
JOptionPane.showMessageDialog(GuiChat.this,"请输入IP地址和端口号");
return;
}
if(datagramSocket==null||datagramSocket.isClosed()){
JOptionPane.showMessageDialog(GuiChat.this,"监听不成功");
return;
}
//获取需要发送的内容
String sendContent=inputTextArea.getText();
byte[] buf=sendContent.getBytes();
try {
//将发送的内容显示在自己的聊天记录中
centerTextArea.append("我对"+ipAddresString+":"+remotePort+"说"+"\n"+inputTextArea.getText()+"\n\n");
//添加内容后,使滚动条自动滚动到最低端
centerTextArea.setCaretPosition(centerTextArea.getText().length());
//发送数据
datagramSocket.send(new DatagramPacket(buf,buf.length ,InetAddress.getByName(ipAddresString),Integer.parseInt(remotePort)));
inputTextArea.setText("");
} catch (Exception e2) {
// TODO: handle exception
JOptionPane.showMessageDialog(GuiChat.this,"出错了,发送不成功");
e2.printStackTrace();
}
};
});
//为clearBT添加监听事件
clearBT.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO 自动生成的方法存根
centerTextArea.setText("");//清空聊天记录的内容
}
});
}
//接受用户填写的程序监听端口号
private void initSocket(){
int port=DEFAULT_PORT;
while (true) {
try {
if (datagramSocket!=null&&!datagramSocket.isClosed()) {
datagramSocket.close();
}
try {//判断端口号是否是1-65535之间
port=Integer.parseInt(JOptionPane.showInputDialog(this,"请输入端口号","端口号",JOptionPane.QUESTION_MESSAGE));
if (port<1 || port>65535) {
throw new RuntimeException("端口号超出范围");
}
} catch (Exception e) {
// TODO: handle exception
JOptionPane.showMessageDialog(null, "您输入的端口号不正确,请输入1-65535之间的端口号");
continue;
}
//启动datagramSocket
datagramSocket=new DatagramSocket(port);
startListen();
//在stateLB中显示程序监听的端口号
stateLB.setText("已在"+port+"端口监听");
break;
} catch (Exception e) {//端口号被占用重新填写
// TODO: handle exception
JOptionPane.showMessageDialog(this,"端口号已被占用,请重新设置端口号");
stateLB.setText("当前还未启动监听");
}
}
}
//接受消息
private void startListen(){
new Thread(){
private DatagramPacket p;
public void run(){
byte [] buf=new byte[1024];
//创建datagramepacket
p=new DatagramPacket(buf, buf.length);
while (!datagramSocket.isClosed()) {
try {
datagramSocket.receive(p);//接受聊天消息
//添加到聊天记录框
centerTextArea.append(p.getAddress().getHostAddress()+":"+((InetSocketAddress)p.getSocketAddress()).getPort()+"对我说:\n"+new String(p.getData(),0,p.getLength())+"\n\n");
//使滚动条自动滚动最低端
centerTextArea.setCaretPosition(centerTextArea.getText().length());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
}.start();
}
public GuiChat(){
setUpUI();
initSocket();
setListener();
}
public static void main(String [] args){
new GuiChat();
}
}