Java聊天室简单,Java项目,小程序,聊天工具

在这里插入图片描述
在这里插入图片描述

package Client;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.TargetDataLine;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.border.TitledBorder;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import Pojo.UserInfo;

//聊天室客户端
public class ChatClient extends JFrame{
	private ChatClient chatClient = this;
	private int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
	private int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
	//图形界面
	private JTextPane txtShow;
	private JTextPane txtShowPri;
	private JTextField txtMsg;
	private JLabel infoName;
	private JLabel infoIp;
	private JButton send;
	private JButton clear;
	private JButton record_start;
	private JButton record_stop_send;
	private JPanel nPanel;
	private JPanel sPanel;
	private JScrollPane rScroll;
	private JScrollPane lScroll;
	private JSplitPane Split;
	private JComboBox<String> comboBox;
	private SimpleAttributeSet attrset;
	
	private DefaultListModel<String> listModel;
	private JList<String> userList;
	
	private Socket socket;
	private static PrintWriter writer; // 写消息
	private static BufferedReader reader; // 读消息
	private MessageThread messageThread = null;// 负责接收消息的线程
	private Map<String, UserInfo> onLineUsers = new HashMap<String, UserInfo>();// 所有在线用户
	private boolean isConnected = false;
	private int port = 30000;
	private String ip = "";
	private String Userip = "";
	private String name;
	private String UserValue = "";
	private int info_ip_ = 0;
	
	public ChatClient(String userName,String ip) {
		//设置窗口属性
		super(userName);
		this.Userip = ip;
		this.name = userName;
		this.setVisible(true);
		this.setResizable(false);
		//用户信息界面
		infoName = new JLabel(userName);
		//消息展示
		txtShow = new JTextPane();
		txtShow.setEditable(false);
		txtShowPri = new JTextPane();
		txtShowPri.setEditable(false);
		//属性集
		attrset = new SimpleAttributeSet();
		StyleConstants.setFontSize(attrset, 15);
		//消息框
		txtMsg = new JTextField();
		//按钮
		send = new JButton("发送");
		clear = new JButton("清屏");
		record_start = new JButton("私聊");
		record_stop_send = new JButton("群聊");
		comboBox = new JComboBox<>();
		comboBox.addItem("ALL");
		//列表
		listModel = new DefaultListModel<>();
		userList = new JList<>(listModel);
		//n面板
		nPanel = new JPanel();
		nPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
		JLabel infoNameTip = new JLabel("用户名 : ");
		TitledBorder infoTitle = new TitledBorder("用户信息");
		infoNameTip.setForeground(Color.WHITE);
		infoName.setForeground(Color.WHITE);
		infoTitle.setTitleColor(Color.WHITE);
		nPanel.add(infoNameTip);
		nPanel.add(infoName);
		nPanel.setBorder(infoTitle);
		//中间面板
		rScroll = new JScrollPane(txtShow);
		TitledBorder txtTitle = new TitledBorder("消息");
		txtTitle.setTitleColor(Color.DARK_GRAY);
		rScroll.setBorder(txtTitle);
		lScroll = new JScrollPane(userList);
		TitledBorder userTitle = new TitledBorder("在线用户");
		userTitle.setTitleColor(Color.DARK_GRAY);
		lScroll.setBorder(userTitle);
		//s面板
		sPanel = new JPanel(new BorderLayout());
		sPanel.setLayout(null);
		txtMsg.setBounds(0,0,600,100);
		txtMsg.setBackground(Color.GRAY);
		send.setBounds(420, 110, 150, 35);
		send.setForeground(Color.DARK_GRAY);
		comboBox.setBounds(30, 110, 100, 35);
		comboBox.setForeground(Color.DARK_GRAY);
		clear.setBounds(160, 110, 100, 35);
		clear.setForeground(Color.DARK_GRAY);
		//record_start.setBounds(290, 110, 100, 35);
		//record_start.setForeground(Color.DARK_GRAY);
		//record_stop_send.setBounds(420, 110, 150, 35);
		//record_stop_send.setForeground(Color.DARK_GRAY);
		sPanel.add(txtMsg);
		sPanel.add(send);
		sPanel.add(comboBox);
		sPanel.add(clear);
		sPanel.add(record_start);
		//sPanel.add(record_stop_send);
		//分割线
		Split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, lScroll, rScroll);
		Split.setDividerLocation(150);
		//窗口属性
		this.setLayout(null);
		nPanel.setBounds(0,0,600,80);
		nPanel.setBackground(Color.GRAY);
		Split.setBounds(0, 90, 600, 500);
		sPanel.setBounds(0,600,600,200);
		//添加组件
		this.add(nPanel);
		this.add(Split);
		this.add(sPanel);
		this.setBounds(0, 0, 600, 800);
		screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
		screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
		//大小
		this.setLocation((screenWidth - chatClient.getWidth()) / 2, (screenHeight - chatClient.getHeight()) / 2);
		this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		
		
		//连接服务器
		ConnectServer();
		//绑定事件
		txtMsg.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				ComboBoxValue();
			}
		});
		//发送消息
		send.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				ComboBoxValue();
			}
		});

		//清屏
		clear.addActionListener(new ClearListener(txtShow));
		
		//关闭窗口
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				if (isConnected) {
					try {
						// 断开连接
						boolean flag = ConnectClose();
						if (flag == false) {
							throw new Exception("断开连接发生异常!");
						} else {
							JOptionPane.showMessageDialog(chatClient, "成功断开!");
							txtMsg.setEnabled(false);
							send.setEnabled(false);
						}
					} catch (Exception e4) {
						JOptionPane.showMessageDialog(chatClient, "断开连接服务器异常:" + e4.getMessage(), "错误",
								JOptionPane.ERROR_MESSAGE);
					}
				} else if (!isConnected) {
					ConnectServer();
					txtMsg.setEnabled(true);
					send.setEnabled(true);
				}
			}
		});
		
		comboBox.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent evt) {
				try {
					if (ItemEvent.SELECTED == evt.getStateChange()) {
						// 这个判断是选择只会得到一个结果,如果没有判断,会得到两个相同的值,从而获取不到所要选中的值。。
						String value = comboBox.getSelectedItem().toString();
						System.out.println(value);
						UserValue = value;
					}
				} catch (Exception e) {
					System.out.println("GGGFFF");
				}
			}
		});
		
		
	}

	// 发送信息
	public static void sendMessage(String message) {
		writer.println(message);
		writer.flush();
	}
	
	// 连接服务器	
	private void ConnectServer() {
		try {
			socket = new Socket(ip, port);// 根据端口号和服务器IP建立连接
			writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
			reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			infoIp = new JLabel(Userip);
			infoIp.setForeground(Color.WHITE);
			if (info_ip_ == 0) {
				nPanel.add(infoIp);
				JOptionPane.showMessageDialog(this, name + " 连接服务器成功!");
			}
			info_ip_++;
			// 发送客户端用户名和IP地址
			sendMessage(name + "@" + "IP" + "@" + Userip);
			sendMessage(name + "@" + "ADD");
			sendMessage(name + "@" + "USERLIST");
			sendMessage(name + "@" + "Login"+"@"+ Userip);
			// 开启接受消息线程
			messageThread = new MessageThread(reader);
			messageThread.start();
			//设置服务器连接状态
			isConnected = true;
			this.setVisible(true);
		} catch (Exception e) {
			isConnected = false;
			JOptionPane.showMessageDialog(this, "连接服务器异常:" + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
		}
	}

	// 断开服务器连接
	@SuppressWarnings("deprecation")//注解忽视警告
	public synchronized boolean ConnectClose() {
		try {
			sendMessage(name + "@" + "DELETE");// 发送断开连接命令
			messageThread.stop();// 停止接受消息线程
			// 关闭连接
			if (reader != null) {
				reader.close();
			}
			if (writer != null) {
				writer.close();
			}
			if (socket != null) {
				socket.close();
			}
			isConnected = false;
			return true;
		} catch (IOException e) {
			JOptionPane.showMessageDialog(this, name + " 断开连接服务器失败!");
			isConnected = true;
			return false;
		}
	}
	
	//发送群聊、私聊信息以及添加上线用户信息
	public void ComboBoxValue() {
		sendMessage(name + "@" + "USERLIST");
		String message = txtMsg.getText();
		if (message == null || message.equals("")) {
			JOptionPane.showMessageDialog(this, "消息不能为空!", "错误", JOptionPane.ERROR_MESSAGE);
			return;
		}
		if (UserValue.equals("ALL")) {
			sendMessage(this.getTitle() + "@" + "ALL" + "@" + message + "@" + "not");

		} else {
			sendMessage(this.getTitle() + "@" + comboBox.getSelectedItem().toString() + "@" + message + "@" + "not");
		}
		txtMsg.setText(null);
	}
	
	//接收消息
	class MessageThread extends Thread {

		private BufferedReader reader;

		// 构造方法
		public MessageThread(BufferedReader reader) {
			this.reader = reader;
		}

		public void run() {
			String message = "";
			while (true) {
				try {
						message = reader.readLine();
						StringTokenizer stringTokenizer = new StringTokenizer(message, "/@");
						// 分割字符串转化为数组读取服务器命令
						String[] str_msg = new String[10];
						int j = 0;
						while (stringTokenizer.hasMoreTokens()) {
							str_msg[j++] = stringTokenizer.nextToken();
						}
						String command = str_msg[1];// 信号
						// 服务器已关闭信号
						if (command.equals("SERVERClOSE")) {
							Document docs = txtShow.getDocument();
							try {
								docs.insertString(docs.getLength(), "服务器已关闭!\\r\\n", attrset);// 对文本进行追加
							} catch (BadLocationException e) {
								e.printStackTrace();
							}
							// text_show.add("服务器已关闭!\r\n", null);
							closeCon();// 关闭连接
							return;// 结束线程
						}
						// 上线更新列表信号
						else if (command.equals("Login")) {
							String username = "";
							String userIp = "";
							username = str_msg[0];
							userIp = str_msg[2];
							UserInfo user = new UserInfo(username, userIp);
							System.out.print("更新上线列表");
							onLineUsers.put(username, user);
							listModel.addElement(username);
							comboBox.addItem(username);
						}
						// 下线更新列表信号
						else if (command.equals("Logout")) {
							String username = str_msg[0];
							UserInfo user = (UserInfo) onLineUsers.get(username);
							onLineUsers.remove(user);
							listModel.removeElement(username);
							comboBox.removeItem(username);
						}
						// 加载用户列表
						else if (command.equals("USERLIST")) {
							String username = null;
							String userIp = null;
							for (int i = 2; i < str_msg.length; i += 2) {
								if (str_msg[i] == null)
									break;
								username = str_msg[i];
								userIp = str_msg[i + 1];
								UserInfo user = new UserInfo(username, userIp);
								onLineUsers.put(username, user);
								if (listModel.contains(username))
									;
								else
									listModel.addElement(username);
								int len = comboBox.getItemCount();
								int _i = 0;
								for (; _i < len; _i++) {
									if (comboBox.getItemAt(_i).toString().equals(username))
										break;
								}
								if (_i == len)
									comboBox.addItem(username);
								else
									;
							}
						}
						// 人数已达上限信号
						else if (command.equals("MAX")) {
							closeCon();// 关闭连接
							JOptionPane.showMessageDialog(chatClient, "服务器人数已满,请稍后再试!", "提示", JOptionPane.CANCEL_OPTION);
							return;// 结束线程
						}
						// 群发消息
						else if (command.equals("ALL")) {
							SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");// 设置日期格式
							String time = df.format(new java.util.Date());
							Document docs = txtShow.getDocument();
							try {
								docs.insertString(docs.getLength(),
										"[" + time + "]\r\n" + str_msg[0] + " 说 : " + str_msg[2] + "\r\n\n", attrset);// 对文本进行追加
							} catch (BadLocationException e) {
								e.printStackTrace();
							}
						
						}
						// 私聊消息
						else if (command.equals("ONLY")) {
							SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");// 设置日期格式
							String time = df.format(new java.util.Date());
							Document docs = txtShow.getDocument();
							try {
								docs.insertString(docs.getLength(), "[" + time + "]\r\n" + str_msg[0] + "\r\n\n",
										attrset);// 对文本进行追加
							} catch (BadLocationException e) {
								e.printStackTrace();
							}
							
						}
						str_msg = null; // 消息数组置空
				} 
				catch (IOException e1) {
					// ConnectServer();
					e1.printStackTrace();
					System.out.println("客户端接受 消息 线程 run() e1:" + e1.getMessage());
					break;
				} catch (Exception e2) {
					// ConnectServer();
					e2.printStackTrace();
					System.out.println("客户端接收 消息 线程 run() e2:" + e2.getMessage());
					break;
				}
			} 
		}

		// 服务器停止后,客户端关闭连接。
		// synchronized用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻只有一个线程执行该段代码。
		public synchronized void closeCon() throws Exception {
			listModel.removeAllElements();// 清空用户列表
			// 被动的关闭连接释放资源
			if (reader != null) {
				reader.close();
			}
			if (writer != null) {
				writer.close();
			}
			if (socket != null) {
				socket.close();
			}
			isConnected = false;// 修改状态为断开
		}
	}
	
	//清屏
	public class ClearListener implements ActionListener{
		private JTextPane txtShow;
		public ClearListener(JTextPane txtShow) {
			this.txtShow = txtShow;
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			txtShow.setText("");
		}
		
	}
}


更多信息关注微信公众号:长长的路我们慢慢走吧
回复:Java考试系统
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值