Java在线聊天室课程设计(嘉然UI界面)

article/2025/10/23 5:14:24

文章目录

  • 一、前言 😆
  • 二、效果展示图 🧐
    • 1、服务器界面
    • 2、客户端登录界面
    • 3、聊天界面
  • 三、客户端Client 🙂
    • 1、LoginFrame类
    • 2、ClientHandler类
    • 3、ChatFrame类
  • 四、服务器端Server 🙃
    • 1、ServerFrame类
    • 2、ServerInfoPanel类
    • 3、OnlineUserPanel类
    • 4、ServerHandler类
    • 5、ChatServer类
  • 五、常量Constants 😳
    • 1、Port 端口
  • 六、输入输出流IO 😋
    • 1、IOStream类
  • 七、实体类entity 😬
    • 1、InfoType消息类型类
    • 2、ServerInfoBean 服务器信息类
    • 3、TransferInfo 传输消息类
    • 4、User 用户类
  • 八、Ulist列表美化 😝
    • 1、ImageCellRenderer 自定义JList渲染器
    • 2、ImageListModel JList模型类
  • 九、整个聊天室写完辣 🤗

一、前言 😆

最近在做JAVA课设,选题是局域网聊天室的实现与设计
忘记了很多知识点,所以整体来说是为了快速应付学校的课设任务

⭐期间借鉴了许多资料,主要知识点:GUI图形化界面、IO输入输出流、网络socket编程⭐

二、效果展示图 🧐

1、服务器界面

在这里插入图片描述

2、客户端登录界面

在这里插入图片描述

3、聊天界面

在这里插入图片描述

三、客户端Client 🙂

1、LoginFrame类

public class LoginFrame extends JFrame {// 设置窗体宽度常量private static final Integer FRAME_WIDTH = 600;// 设置窗体高度常量private static final Integer FRAME_HEIGHT = 400;//构造方法public LoginFrame() {//下面对LoginFrame的设置加不加this.都行setTitle("❤CHAT ROOM❤");	//设置标题setSize(FRAME_WIDTH, FRAME_HEIGHT);	//设置尺寸setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);	//设置关闭模式setResizable(false);	//窗口是否可缩放(不行)// 获取屏幕像素并确定计算窗口位置居中,两种方法setLocationRelativeTo(null);//	Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();//	int screenWidth = screenSize.width;//	int screenheight = screenSize.height;//	setLocation((screenWidth - FRAME_WIDTH) / 2, (screenheight - FRAME_HEIGHT) / 2);//标题图标,把咖啡杯换成嘉然的头像Toolkit toolkit=Toolkit.getDefaultToolkit();Image topIcon=toolkit.getImage("src/image/bg/login-icon.jpg");setIconImage(topIcon);// 背景图片,把图片放在JLabel标签里ImageIcon imageBg = new ImageIcon("src/image/bg/JRbg.jpg");JLabel jlbBg = new JLabel(imageBg);// 图片的位置和大小【不设置也不影响】jlbBg.setBounds(0, 0, FRAME_WIDTH, FRAME_HEIGHT);jlbBg.setLayout(null);	// 布局为空布局add(jlbBg);	//LoginFrame加入标签组件// 标题JLabel lblTitle = new JLabel("❤ CHAT   ROOM ❤");	lblTitle.setBounds(150, 35, 350, 55);	// x,y,宽,高lblTitle.setFont(new Font("PingFang SC", Font.BOLD, 36));	//苹方字体,加粗,36尺寸lblTitle.setForeground(Color.RED);	//字体红色jlbBg.add(lblTitle);	//大背景图加入标题组件// 账户JLabel lblUid = new JLabel("ACCOUNT:");lblUid.setBounds(150, 120, 110, 30);	//x,y,宽,高lblUid.setFont(new Font("PingFang SC", Font.BOLD, 16));lblUid.setForeground(Color.BLACK);jlbBg.add(lblUid);//账户文本框JTextField textUid = new JTextField();textUid.setBounds(260, 120, 160, 30);jlbBg.add(textUid);// 密码【和账户设置差不多】JLabel lblPwd = new JLabel("PASSWORD:");lblPwd.setBounds(150, 180, 110, 30);lblPwd.setFont(new Font("PingFang SC", Font.BOLD, 16));lblPwd.setForeground(Color.BLACK);jlbBg.add(lblPwd);//密码文本框JPasswordField textPwd = new JPasswordField();textPwd.setBounds(260, 180, 160, 30);jlbBg.add(textPwd);// 登录按钮JButton login = new JButton("LOGIN");login.setBounds(175, 250, 103, 30);login.setBackground(Color.PINK);	//背景粉色login.setForeground(Color.WHITE);	//字体白色login.setFont(new Font("PingFang SC", Font.BOLD, 16));//登录按钮监听login.addActionListener(new ActionListener() {	//匿名内部类,只在登录时使用一次@Overridepublic void actionPerformed(ActionEvent e) {String username = textUid.getText();	//获取用户名String password = textPwd.getText();	//获取密码TransferInfo transferInfo = new TransferInfo();	//实例化传输信息对象transferInfo.setUsername(username);	//设置用户名transferInfo.setPassword(password);	//设置密码transferInfo.setStatusEnum(ChatStatus.LOGIN);	//设置信息为登录connectionServer(transferInfo);	 //与服务器连接}});jlbBg.add(login); // 取消按钮JButton cancel = new JButton("CANCEL");cancel.setBounds(355, 250, 103, 30);cancel.setBackground(Color.PINK);cancel.setForeground(Color.WHITE);cancel.setFont(new Font("PingFang SC", Font.BOLD, 16));jlbBg.add(cancel);setVisible(true);	//设置可视化//连接服务器的方法public void connectionServer(TransferInfo transferInfo) {try {Socket socket = new Socket("127.0.0.1", 8888);	//创建socket(主机,端口)//写一个消息IOStream.writeMessage(socket, transferInfo);//开启客户端子线程,接收消息ClientHandler clientHandler = new ClientHandler(socket, this);clientHandler.start();} catch (UnknownHostException e1) {	//捕获一下异常// TODO Auto-generated catch blocke1.printStackTrace();} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}System.out.println("点击了login按钮");}//主函数:启动登录界面public static void main(String[] args) {new LoginFrame();}}
}

2、ClientHandler类

// 客户端开启一个线程,来一起读消息
public class ClientHandler extends Thread {Socket socket;	//声明socketLoginFrame loginFrame;	//登录界面ChatFrame chatFrame;	//聊天界面//含参构造方法(socket,登录界面)public ClientHandler(Socket socket, LoginFrame loginFrame) {this.socket = socket;this.loginFrame = loginFrame;}@Overridepublic void run() {while (true) {// 模拟一直读消息Object object = IOStream.readMessage(socket);//如果读到的对象属于传输消息这类//if (object instanceof TransferInfo) {TransferInfo transferInfo = (TransferInfo) object;if (transferInfo.getStatusEnum() == InfoType.LOGIN) {//登录消息loginResult(transferInfo);}else if (transferInfo.getStatusEnum() == InfoType.CHAT) {//聊天消息chatResult(transferInfo);}else if (transferInfo.getStatusEnum() == InfoType.NOTICE) {//系统消息noticeResult(transferInfo);}else if (transferInfo.getStatusEnum() == InfoType.ULIST) {//刷新当前在线用户列表onlineUsersResult(transferInfo);}//}}}/*** 登录消息处理*/public void loginResult(TransferInfo transferInfo) {if (transferInfo.getLoginSuccess()) {//登录成功,跳转主页面String username = transferInfo.getUsername();chatFrame = new ChatFrame(username, socket);//关闭登录窗口loginFrame.dispose();}else{//登录失败System.out.println("客户端接收到登录失败");System.out.println(transferInfo.getNotice());}}/*** 系统消息处理*/public void noticeResult(TransferInfo transferInfo) {//在公屏上显示系统消息String originText = chatFrame.acceptPane.getText();if (!originText.isEmpty()) {chatFrame.acceptPane.setText(originText + "\n" + transferInfo.getNotice());}else{chatFrame.acceptPane.setText(transferInfo.getNotice());}}/*** 聊天消息处理*/public void chatResult(TransferInfo transferInfo) {String sender = transferInfo.getSender();String originText = chatFrame.acceptPane.getText();chatFrame.acceptPane.setText(originText + "\n" + "> " + sender + ":" + transferInfo.getContent());}/*** 刷新当前界面的用户列表*/public void onlineUsersResult(TransferInfo transferInfo) {String[] userOnlineArray = transferInfo.getUserOnlineArray();ImageListModel model = new ImageListModel();for (String username: userOnlineArray){//头像User user = new User();user.setUserName(username);user.setUiconPath("src/image/" + username + ".jpg");
//			System.out.println(user.getUiconPath());user.setMotto("❤然然可爱捏❤");model.addElement(user);}//JList的模型,给我们存放数据chatFrame.lstUser.setModel(model);//提供给我们自定义想要的皮肤或样式chatFrame.lstUser.setCellRenderer(new ImageCellRenderer());
//		chatFrame.lstUser.setListData(userOnlineArray);}
}

3、ChatFrame类

//聊天界面
public class ChatFrame extends JFrame {private static final long serialVersionUID = 1709267049032639256L;// 聊天窗体宽度public static final Integer FRAME_WIDTH = 800;// 聊天窗体高度public static final Integer FRAME_HEIGHT = 700;//消息接受框public JTextPane acceptPane;//当前在线用户列表public JList lstUser;String username;Socket socket;ChatFrame chatFrame;JTextPane sendPane;JComboBox reciverBox;public ChatFrame(String username, Socket socket) {setTitle("CHAT ROOM");this.username = username;this.socket = socket;chatFrame = this;setSize(FRAME_WIDTH, FRAME_HEIGHT);setResizable(false);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//固定在屏幕中间setLocationRelativeTo(null);
//    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
//    int width = screenSize.width;
//    int height = screenSize.height;
//    setLocation((width - FRAME_WIDTH) / 2, (height - FRAME_HEIGHT) / 2);// 加载窗体的背景图片ImageIcon imageIcon = new ImageIcon("src/image/bg/JRbg.jpg");JLabel frameBg = new JLabel(imageIcon);frameBg.setBounds(0, 0, FRAME_WIDTH, FRAME_HEIGHT);add(frameBg);//标题图标,把咖啡杯换成嘉然的头像Toolkit toolkit=Toolkit.getDefaultToolkit();Image topIcon=toolkit.getImage("src/image/bg/chatframe-icon.jpg");setIconImage(topIcon);// 接收框acceptPane = new JTextPane();acceptPane.setOpaque(true); // 不透明acceptPane.setFont(new Font("PingFang SC",Font.BOLD, 16));// 接收滚动条JScrollPane scrollPaneOne = new JScrollPane(acceptPane);scrollPaneOne.setBounds(225, 20, 500, 332);scrollPaneOne.setOpaque(false);scrollPaneOne.getViewport().setOpaque(false);frameBg.add(scrollPaneOne);// 当前在线用户列表lstUser = new JList();lstUser.setFont(new Font("PingFang SC",Font.BOLD, 14));lstUser.setVisibleRowCount(17);lstUser.setFixedCellWidth(180);lstUser.setFixedCellHeight(60);JPopupMenu popupMenu = new JPopupMenu();JMenuItem privateChat = new JMenuItem("PRIVATE");privateChat.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {Object reciverObj = lstUser.getSelectedValue();if (reciverObj instanceof User) {User user = (User) reciverObj;String reciver = user.getUserName();reciverBox.removeAllItems();reciverBox.addItem("ALL");reciverBox.addItem(reciver);reciverBox.setSelectedItem(reciver);}}});popupMenu.add(privateChat);
//    JMenuItem blackList = new JMenuItem("BLACK");
//    blackList.addActionListener(new ActionListener() {
//
//       @Override
//       public void actionPerformed(ActionEvent e) {
//          // TODO Auto-generated method stub
//
//       }
//    });
//    popupMenu.add(blackList);//添加点击事件,需要确认是右键。lstUser.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {//监听左键|右键if (e.isMetaDown() && lstUser.getSelectedIndex() >= 0) {//弹出菜单popupMenu.show(lstUser, e.getX(), e.getY());}}});JScrollPane spUser = new JScrollPane(lstUser);spUser.setFont(new Font("PingFang SC", Font.BOLD, 15));spUser.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);spUser.setBounds(15, 17, 200, 507);frameBg.add(spUser);// 输入框sendPane = new JTextPane();sendPane.setOpaque(true);sendPane.setFont(new Font("PingFang SC", Font.BOLD, 16));JScrollPane scoPane = new JScrollPane(sendPane);// 设置滚动条scoPane.setBounds(225, 400, 500, 122);scoPane.setOpaque(false);scoPane.getViewport().setOpaque(false);frameBg.add(scoPane);//私聊标签JLabel chatLabel = new JLabel("CHAT  TO:");chatLabel.setBounds(505, 362, 80, 25);chatLabel.setFont(new Font("PingFang SC", Font.BOLD, 13));frameBg.add(chatLabel);//ALL、私聊下拉选择框reciverBox = new JComboBox();reciverBox.setSelectedItem("ALL");reciverBox.addItem("ALL");reciverBox.setBounds(580, 362, 150, 25);frameBg.add(reciverBox);/** 发送按钮*/JButton send = new JButton("SEND");send.setBounds(605, 545, 125, 30);send.setFont(new Font("PingFang SC", Font.BOLD, 16));send.setForeground(Color.WHITE);send.setBackground(Color.PINK);send.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String content = sendPane.getText();TransferInfo transferInfo = new TransferInfo();transferInfo.setContent(content);//发送人transferInfo.setSender(username);String reciver = "ALL";Object reciverObj = reciverBox.getSelectedItem();if (reciverObj != null) {reciver = String.valueOf(reciverObj);}System.out.println("MESSAGE:" + reciver);//接收人transferInfo.setReciver(reciver);transferInfo.setStatusEnum(InfoType.CHAT);IOStream.writeMessage(socket, transferInfo);sendPane.setText("");}});frameBg.add(send);//客户端关闭窗体退出this.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {try {System.out.println(username + "CLOSE");TransferInfo tfi = new TransferInfo();tfi.setStatusEnum(InfoType.EXIT);tfi.setUsername(username);tfi.setNotice(username + "  LEAVING.....");IOStream.writeMessage(socket, tfi);} catch (Exception e1) {e1.printStackTrace();}}});//切换背景图片按钮ImageIcon alterBtn=new ImageIcon("src/image/bg/alterbtn.jpg");JButton alterBg=new JButton(alterBtn);
//		Image temp=alterBtn.getImage().getScaledInstance(alterBg.getWidth(),alterBg.getHeight(),
//				alterBtn.getImage().SCALE_DEFAULT);
//		alterBtn=new ImageIcon(temp);
//		alterBg.setIcon(alterBtn);alterBg.setBounds(36, 535, 136, 136);alterBg.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {tapCnt++;if(tapCnt%3==1){frameBg.setIcon(new ImageIcon("src/image/bg/alterBg-1.jpg"));}else if(tapCnt%3==2){frameBg.setIcon(new ImageIcon("src/image/bg/alterBg-2.jpg"));}else{frameBg.setIcon(new ImageIcon("src/image/bg/JRbg.jpg"));}}});frameBg.add(alterBg);setVisible(true);}
}

四、服务器端Server 🙃

1、ServerFrame类

//服务器界面
public class ServerFrame extends JFrame {//随机生成序列号private static final long serialVersionUID=-8235369520375669451L;//服务器窗体宽度public static final Integer FRAME_WIDTH = 600;//服务器窗体高度public static final Integer FRAME_HEIGHT = 600;//声明用户列表【选项卡2】public OnlineUserPanel onlineUserPanel;//声明服务器信息【选项卡1】public ServerInfoPanel serverInfoPanel;//构造方法public ServerFrame() {setTitle("❤SERVER❤");	//标题setSize(FRAME_WIDTH, FRAME_HEIGHT);	//窗口大小setResizable(false);	//不可缩放窗口setLocationRelativeTo(null);	// 窗口居中
//		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
//		int screenWidth = screenSize.width;
//		int screenheight = screenSize.height;
//		setLocation((screenWidth - FRAME_WIDTH) / 2, (screenheight - FRAME_HEIGHT) / 2);//标题图标,把咖啡杯换成嘉然的头像Toolkit toolkit=Toolkit.getDefaultToolkit();Image topIcon=toolkit.getImage("src/image/bg/server-icon.jpg");setIconImage(topIcon);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);		//退出应用程序// 选项卡(服务器信息+在线用户面板)JTabbedPane tpServer = new JTabbedPane(JTabbedPane.TOP);	//标签位于上方tpServer.setBackground(Color.WHITE);	//设置背景颜色tpServer.setFont(new Font("PingFang SC",Font.BOLD,20));//实例化两个选项卡serverInfoPanel = new ServerInfoPanel();onlineUserPanel = new OnlineUserPanel();//选项卡加入服务器信息和在线用户面板tpServer.add("SERVER INFO", serverInfoPanel.getServerInfoPanel());	//方法是返回一个面板tpServer.add("ONLINE USER", onlineUserPanel.getUserPanel());add(tpServer);	//服务器界面加入选项卡setVisible(true);}}

2、ServerInfoPanel类

//【第一个服务器信息选项卡】
public class ServerInfoPanel {public JTextField txtNumber;	//人数public JTextField txtServerName;	//服务器名称public JTextField txtIP;		//IP地址public JTextField txtPort;		//端口号public JTextPane txtLog;		//日志文本public JLabel getServerInfoPanel() {// 第一个服务选项卡面板,包括日志区域JPanel pnlServer = new JPanel();pnlServer.setOpaque(false);pnlServer.setLayout(null);pnlServer.setBounds(0, 0, ServerFrame.FRAME_WIDTH, ServerFrame.FRAME_HEIGHT);// 日志标签JLabel lblLog = new JLabel("❤LOG❤");lblLog.setForeground(Color.RED);lblLog.setFont(new Font("PingFang SC", Font.BOLD, 20));lblLog.setBounds(150, 10, 100, 30);pnlServer.add(lblLog);	//选项卡加入日志标签组件// 日志区域txtLog = new JTextPane();txtLog.setBackground(Color.BLACK);txtLog.setForeground(Color.PINK);txtLog.setOpaque(true);txtLog.setFont(new Font("PingFang SC", Font.BOLD, 18));//日志显示屏JScrollPane scoPaneOne = new JScrollPane(txtLog);// 设置滚动条,把txtLog塞进去scoPaneOne.setBounds(155, 40, 390, 390);scoPaneOne.setOpaque(false);//设置聊天框与滚动条像素透明,露出下方背景像素//【JSCrollPane有两个面板层,一个是他本身,而另外一个则是他的viewport(视口)】scoPaneOne.getViewport().setOpaque(false);//面板加入日志显示屏pnlServer.add(scoPaneOne);//停止按钮pnlServer.add(stopBtn());//保存按钮pnlServer.add(saveLogBtn());//左边四行参数pnlServer.add(getServerParam());// 加载窗体的背景图片ImageIcon imageIcon = new ImageIcon("src/image/bg/JRbg.jpg");// 创建一个标签并将图片添加进去JLabel lblBackground = new JLabel(imageIcon);// 设置图片的位置和大小lblBackground.setBounds(0, 0, 300, 300);// 添加到当前窗体中lblBackground.add(pnlServer);//返回标签背景return lblBackground;}public JPanel getServerParam() {// 左边服务器参数信息面板,不包括日志区域JPanel serverParamPanel = new JPanel();serverParamPanel.setOpaque(false);	//设置透明serverParamPanel.setBounds(12, 35, 120, 360);serverParamPanel.setFont(new Font("PingFang SC", Font.BOLD, 15));//在线人数标签JLabel lblNumber = new JLabel("ONLINE:");lblNumber.setForeground(Color.ORANGE);lblNumber.setFont(new Font("PingFang SC", Font.BOLD, 15));serverParamPanel.add(lblNumber);//在线人数文本框txtNumber = new JTextField("0", 14);txtNumber.setFont(new Font("PingFang SC", Font.BOLD, 15));txtNumber.setEditable(false);txtNumber.setHorizontalAlignment(JTextField.CENTER);	//文本框居中serverParamPanel.add(txtNumber);//主机名标签JLabel lblServerName = new JLabel("NAME:");lblServerName.setForeground(Color.ORANGE);lblServerName.setFont(new Font("PingFang SC", Font.BOLD, 15));serverParamPanel.add(lblServerName);//主机名文本框txtServerName = new JTextField(14);txtServerName.setFont(new Font("PingFang SC", Font.BOLD, 15));txtServerName.setEditable(false);txtServerName.setHorizontalAlignment(JTextField.CENTER);	//文本框居中serverParamPanel.add(txtServerName);//IP标签JLabel lblIP = new JLabel("IP:");lblIP.setForeground(Color.ORANGE);lblIP.setFont(new Font("PingFang SC", Font.BOLD, 15));serverParamPanel.add(lblIP);//IP文本框txtIP = new JTextField(14);txtIP.setFont(new Font("PingFang SC", Font.BOLD, 15));txtIP.setEditable(false);txtIP.setHorizontalAlignment(JTextField.CENTER);	//文本框居中serverParamPanel.add(txtIP);//端口号标签JLabel lblPort = new JLabel("PORT:");lblPort.setForeground(Color.ORANGE);lblPort.setFont(new Font("PingFang SC", Font.BOLD, 15));serverParamPanel.add(lblPort);//端口号文本框txtPort = new JTextField(Port.SERVER_PORT + "", 14);txtPort.setFont(new Font("PingFang SC", Font.BOLD, 15));txtPort.setEditable(false);	//禁止编辑txtPort.setHorizontalAlignment(JTextField.CENTER);	//文本框居中serverParamPanel.add(txtPort);return serverParamPanel;}//服务器关闭按钮public JButton stopBtn() {JButton stopBtn = new JButton("CLOSE");stopBtn.setBackground(Color.PINK);stopBtn.setForeground(Color.WHITE);stopBtn.setFont(new Font("PingFang SC", Font.BOLD, 15));stopBtn.setBounds(180, 450, 120, 35);return stopBtn;}//保存日志按钮public JButton saveLogBtn() {JButton saveLogBtn = new JButton("SAVE");saveLogBtn.setBackground(Color.PINK);saveLogBtn.setForeground(Color.WHITE);saveLogBtn.setFont(new Font("PingFang SC", Font.BOLD, 15));saveLogBtn.setBounds(390, 450, 120, 35);return saveLogBtn;}
}

3、OnlineUserPanel类

//【第二个在线用户选项卡】
public class OnlineUserPanel {//用户public JList lstUser;//在线用户标签public JLabel getUserPanel() {JPanel pnlUser = new JPanel();pnlUser.setLayout(null);	pnlUser.setBackground(Color.PINK);pnlUser.setBounds(30, 5, 480, 400);pnlUser.setOpaque(false);// 设置透明JLabel lblUser = new JLabel("❤ ONLINE  LIST ❤");lblUser.setFont(new Font("PingFang SC", Font.BOLD, 20));lblUser.setBounds(20, 10, 200, 30);lblUser.setForeground(Color.PINK);pnlUser.add(lblUser);	//标题标签加到大面板// 用户列表lstUser = new JList();lstUser.setFont(new Font("PingFang SC", Font.BOLD, 16));lstUser.setVisibleRowCount(17);		//设置列表可见行数lstUser.setFixedCellWidth(180);		//单元宽度lstUser.setFixedCellHeight(35);		//单元高度lstUser.setOpaque(false);JScrollPane spUser = new JScrollPane(lstUser);	//实例化含用户列表的滚动面板spUser.setFont(new Font("PingFang SC", Font.BOLD, 14));spUser.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);spUser.setBounds(30, 45, 440, 360);spUser.setOpaque(false);pnlUser.add(spUser);	//滚动面板加到大面版// 加载窗体的背景图片ImageIcon imageIcon = new ImageIcon("src/image/bg/JRbg.jpg");// 创建一个标签并将图片添加进去JLabel lblBackground = new JLabel(imageIcon);// 设置图片的位置和大小lblBackground.setBounds(0, 200, 300, 300);// 添加到当前窗体中lblBackground.add(pnlUser);//返回大面板return lblBackground;}
}

4、ServerHandler类

//服务器启动一个线程,一直读消息
public class ServerHandler extends Thread {Socket socket;	ServerFrame serverFrame;public ServerHandler(Socket socket, ServerFrame serverFrame) {this.socket = socket;this.serverFrame = serverFrame;}static ArrayList<String> onlineUsers = new ArrayList<>();	static ArrayList<Socket> onlineSockets = new ArrayList<>();@Overridepublic void run() {// 默认重复拿while (true) {// 模拟一直拿消息Object object = IOStream.readMessage(socket);		//从socket当中读取消息System.out.println("Server receive:" + object);// if (object instanceof TransferInfo) {		//如果读取的对象是TransferInfo的实例化TransferInfo transferInfo = (TransferInfo) object;	//将对象强整形if (transferInfo.getStatusEnum() == InfoType.LOGIN) {//登录消息类型loginHandler(transferInfo);}else if (transferInfo.getStatusEnum() == InfoType.CHAT) {//聊天信息类型chatHandler(transferInfo);}else if (transferInfo.getStatusEnum() == InfoType.EXIT) {//退出聊天类型logout(transferInfo);try {Thread.sleep(1000);socket.close();    //关闭socket连接} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}this.interrupt();//关闭当前线程break;}// }}}//客户端登录处理public void loginHandler(TransferInfo transferInfo) {boolean flag = checkUserLogin(transferInfo);transferInfo.setLoginSuccess(false);if (flag) {//返回登录成功给客户端(登录消息)transferInfo.setLoginSuccess(true);transferInfo.setStatusEnum(InfoType.LOGIN);IOStream.writeMessage(socket, transferInfo);String username = transferInfo.getUsername();//统计在线人数onlineUsers.add(username);onlineSockets.add(socket);ChatServer.userSocketMap.put(username, socket);//返回用户上线信息给所有用户(系统消息)transferInfo = new TransferInfo();transferInfo.setStatusEnum(InfoType.NOTICE);String notice = ">>  ❤ Welcome " + username + " ❤";transferInfo.setNotice(notice);sendAll(transferInfo); //发送最新的用户列表给客户端transferInfo = new TransferInfo();transferInfo.setUserOnlineArray(onlineUsers.toArray(new String[onlineUsers.size()]));transferInfo.setStatusEnum(InfoType.ULIST);sendAll(transferInfo);//刷新在线用户列表flushOnlineUserList();//发送信息给服务器日志log(notice);}else{//返回登录失败给客户端IOStream.writeMessage(socket, transferInfo);log(transferInfo.getUsername() + "LOGIN FAILED!");}}public void log(String log) {Date date = new Date();SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String dateStr = simpleDateFormat.format(date);JTextPane txtLog = serverFrame.serverInfoPanel.txtLog;String oldLog = txtLog.getText();txtLog.setText(oldLog + "\n" + dateStr + ":" + log);}//刷新用户列表(当一个用户上线时,便刷新)public void flushOnlineUserList() {JList lstUser = serverFrame.onlineUserPanel.lstUser;String[] userArray = onlineUsers.toArray(new String[onlineUsers.size()]);lstUser.setListData(userArray);serverFrame.serverInfoPanel.txtNumber.setText(userArray.length + "");}//广播给所有人public void sendAll(TransferInfo transferInfo) {for (int i = 0; i < onlineSockets.size(); i++){Socket tempSocket = onlineSockets.get(i);IOStream.writeMessage(tempSocket, transferInfo);}}//私聊public void send(TransferInfo transferInfo) {String reciver = transferInfo.getReciver();String sender = transferInfo.getSender();Socket socket1 = ChatServer.userSocketMap.get(reciver);IOStream.writeMessage(socket1, transferInfo);Socket socket2 = ChatServer.userSocketMap.get(sender);IOStream.writeMessage(socket2, transferInfo);}// 处理客户端聊天请求public void chatHandler(TransferInfo transferInfo) {String reciver = transferInfo.getReciver();if ("ALL".equals(reciver)) {//发送给所有人sendAll(transferInfo);}else{//私聊send(transferInfo);}}//验证登录public boolean checkUserLogin(TransferInfo transferInfo) {try {String username = transferInfo.getUsername();String password = transferInfo.getPassword();FileInputStream fileInputStream = new FileInputStream(new File("src/user.txt"));DataInputStream dataInputStream = new DataInputStream(fileInputStream);String row = null;while ((row = dataInputStream.readLine()) != null) {//从文件中读取的行String fileUser = row;if ((username + "@" + password).equals(row)) {System.out.println("Name and Password are correct!");return true;}else{System.out.println("Login failed!");}}} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return false;}//用户退出处理,清理在线人数,刷新用户列表,告诉所有人,你已经离开private void logout(TransferInfo transferInfo) {String userName = transferInfo.getUsername();//将该用户从用户集合移除Iterator<String> userIter = onlineUsers.iterator();while(userIter.hasNext()) {if(userIter.next().equals(userName)) {userIter.remove();}}//将该用户从socket集合移除Iterator<Socket> socketIter = onlineSockets.iterator();while(socketIter.hasNext()) {Socket next = socketIter.next();if(socket == next) {socketIter.remove();}}//将user与Socket的关系从Map中移除ChatServer.userSocketMap.remove(userName);//刷新服务器面板的用户列表flushOnlineUserList();//给所有在线的用户发送下线消息transferInfo.setStatusEnum(InfoType.NOTICE);sendAll(transferInfo);//告诉其他人刷新用户列表transferInfo.setUserOnlineArray(onlineUsers.toArray(new String [onlineUsers.size()]));transferInfo.setStatusEnum(InfoType.ULIST);sendAll(transferInfo);}}

5、ChatServer类

//服务器启动
public class ChatServer {static HashMap<String, Socket> userSocketMap = new HashMap<>();public ServerFrame serverFrame;public ChatServer() {try{//建立服务器Socket监听 ServerSocket serverSocket = new ServerSocket(Port.SERVER_PORT);    //端口号:8888//打开服务器界面serverFrame = new ServerFrame();ServerInfoBean serverInfo = getServerIP();loadServerInfo(serverInfo);//解决多客户端连接的循环while(true){//等待连接,阻塞实现,会得到一个客户端连接Socket socket = serverSocket.accept();//启动一个线程来一直接收消息ServerHandler serverHandler = new ServerHandler(socket, serverFrame);serverHandler.start();System.out.println("CONNECTED:" + socket);}}catch (IOException e) {e.printStackTrace();}}//获取服务器的主机名和IP地址,返回服务器IP等信息public ServerInfoBean getServerIP() {ServerInfoBean sib = null;try {InetAddress serverAddress = InetAddress.getLocalHost();byte[] ipAddress = serverAddress.getAddress();sib = new ServerInfoBean();sib.setIp(serverAddress.getHostAddress());sib.setHostName(serverAddress.getHostName());sib.setPort(Port.SERVER_PORT);System.out.println("Server IP is:" + (ipAddress[0] & 0xff) + "."+ (ipAddress[1] & 0xff) + "." + (ipAddress[2] & 0xff) + "."+ (ipAddress[3] & 0xff));} catch (Exception e) {System.out.println("CouLd not get Server IP." + e);}return sib;}public void loadServerInfo(ServerInfoBean serverInfo) {serverFrame.serverInfoPanel.txtIP.setText(serverInfo.getIp());serverFrame.serverInfoPanel.txtServerName.setText(serverInfo.getHostName());serverFrame.serverInfoPanel.txtLog.setText("❤ SERVER SUCCESS ❤");}//主函数public static void main(String[] args) {new ChatServer();}
}

五、常量Constants 😳

1、Port 端口

随便设置,只要不被占用即可😉

public class Port {//服务器端口8888public final static Integer SERVER_PORT = 8888;
}

六、输入输出流IO 😋

1、IOStream类

public class IOStream {//读消息public static Object readMessage(Socket socket) {	Object object = null;try {InputStream inputStream = socket.getInputStream();ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);object = objectInputStream.readObject();} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return object; //返回读到的对象}//写消息public static void writeMessage(Socket socket, Object message) {try {OutputStream outputStream = socket.getOutputStream();ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);objectOutputStream.writeObject(message);objectOutputStream.flush();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}

七、实体类entity 😬

1、InfoType消息类型类


public enum InfoType {LOGIN(1, "登录"),NOTICE(2, "系统消息"),CHAT(3, "聊天消息"),ULIST(4, "在线用户列表"),EXIT(5, "退出");private Integer status;private String desc;private InfoType(int status, String desc) {this.status = status;this.desc = desc;}public Integer getStatus() {return status;}public void setStatus(Integer status) {this.status = status;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}}

2、ServerInfoBean 服务器信息类


public class ServerInfoBean implements Serializable {private static final long serialVersionUID = 4800399407766443229L;private String hostName;private String ip;private Integer port;public String getHostName() {return hostName;}public void setHostName(String hostName) {this.hostName = hostName;}public String getIp() {return ip;}public void setIp(String ip) {this.ip = ip;}public Integer getPort() {return port;}public void setPort(Integer port) {this.port = port;}}

3、TransferInfo 传输消息类

package com.xy.chatting.entity;import java.io.Serializable;public class TransferInfo implements Serializable {private static final long serialVersionUID = -8501366066504250232L;private String username;         //用户名private String password;         //密码private String content;             //聊天内容private Boolean loginSuccess;     //登录成功标志private String notice;          //系统消息private InfoType statusEnum;      //消息类型private String[] userOnlineArray;  //在线用户列表private String sender;          //消息发送人private String reciver;             //消息接收者public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public Boolean getLoginSuccess() {return loginSuccess;}public void setLoginSuccess(Boolean loginSuccess) {this.loginSuccess = loginSuccess;}public String getNotice() {return notice;}public void setNotice(String notice) {this.notice = notice;}public InfoType getStatusEnum() {return statusEnum;}public void setStatusEnum(InfoType statusEnum) {this.statusEnum = statusEnum;}public String[] getUserOnlineArray() {return userOnlineArray;}public void setUserOnlineArray(String[] userOnlineArray) {this.userOnlineArray = userOnlineArray;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public String getSender() {return sender;}public void setSender(String sender) {this.sender = sender;}public String getReciver() {return reciver;}public void setReciver(String reciver) {this.reciver = reciver;}}

4、User 用户类

public class User implements Serializable{private static final long serialVersionUID = 5126205470509431771L;private String userName;private String motto;
// private String nickName;private String uiconPath;public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getMotto() {return motto;}public void setMotto(String motto) {this.motto = motto;}
// public String getNickName() {
//    return nickName;
   }
// public void setNickName(String nickName) {
//    this.nickName = nickName;
// }public String getUiconPath() {return uiconPath;}public void setUiconPath(String uiconPath) {this.uiconPath = uiconPath;}
}

八、Ulist列表美化 😝

1、ImageCellRenderer 自定义JList渲染器

public class ImageCellRenderer extends DefaultListCellRenderer {private static final long serialVersionUID = -6233481640415228808L;@Overridepublic Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {if(value instanceof User) {User user = (User) value;String uiconPath = user.getUiconPath();String userName = user.getUserName();String motto = user.getMotto();ImageIcon icon = new ImageIcon(uiconPath);icon.setImage(icon.getImage().getScaledInstance(55, 55, Image.SCALE_DEFAULT));setIcon(icon);String text = "<html><body><span color='#00B8D8' style='font-size:16px;'>" + userName + "</span><br/>" + motto + "</body></html>";setText(text);if (isSelected) {        //当某个元素被选中时setBackground(Color.LIGHT_GRAY);        //设置背景色}else {setForeground(Color.GRAY);}setVerticalTextPosition(SwingConstants.TOP);setHorizontalTextPosition(SwingConstants.RIGHT);}return this;}
}

2、ImageListModel JList模型类

package com.xy.chatting.ulist;import java.util.List;
import java.util.ArrayList;import javax.swing.AbstractListModel;import com.xy.chatting.entity.User;/*** JList的模型类*/
public class ImageListModel extends AbstractListModel<User> {private static final long serialVersionUID = 8116378668465150072L;private ArrayList<User> list = new ArrayList<User>();public void addElement(User str) {list.add(str);}@Overridepublic User getElementAt(int index) {return list.get(index);}@Overridepublic int getSize() {// TODO Auto-generated method stubreturn list.size();}}

九、整个聊天室写完辣 🤗


http://chatgpt.dhexx.cn/article/SFfaP9kB.shtml

相关文章

java聊天室源代码(练习项目)

聊天室界面如下&#xff1a; 聊天室源代码链接 一、服务端&#xff1a; 窗体&#xff1a; package sonyi.server;import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import jav…

Java—简易聊天室

Java—聊天室的实现 在学习了IO流&#xff0c;多线程以及网络编程的知识之后&#xff0c;我们可以利用所学到的知识做一个小项目&#xff0c;这里我做了一个多人聊天室&#xff0c;实现了群聊和私聊功能&#xff0c;看完分享之后也可以自己去做一个练练手。 首先是整个项目的…

java聊天室(实训项目)

这里是我们实训的一个关于java聊天室的项目&#xff0c;有需要的同学可以看看&#xff0c;私聊功能未完善。 话不多说&#xff0c;直接上代码。 服务器&#xff1a; package ChatRoom;import java.awt.Color; import java.awt.Component; import java.awt.EventQueue; impor…

Java实现简易聊天室

Java实现简易聊天室 在学习《Java从入门到精通》这本书&#xff0c;网络通信&#xff0c;基于TCP实现的简易聊天室&#xff0c;我这里对书中的代码略做了修改&#xff0c;做个记录。 这里先放一下运行效果图&#xff0c;代码放在最后。 运行效果&#xff1a; 先启动服务器端&am…

javaWeb实现聊天室(私聊+群聊)

写在前面 近几天&#xff0c;迎来了第一个小项目&#xff0c;不做不知道&#xff0c;一做吓一跳。好多知识都掌握的不够扎实&#xff0c;看似会了&#xff0c;但其实似懂非懂&#xff0c;不能真正掌握原理&#xff0c;导致使用起来错误百出。而且深深体会到&#xff0c;知识只有…

java实现聊天室(GUI界面+私聊+群聊)

登录界面的用户名和端口号不能重复&#xff01; 登录界面的用户名和端口号不能重复&#xff01; 登录界面的用户名和端口号不能重复&#xff01; java的socket编写的聊天室&#xff0c;GUI的界面&#xff0c;可以私聊和群聊&#xff0c; 聊天信息保存为txt 有需要的可以自行下…

用Java代码实现一个简单的聊天室功能

一.客户端的创建 1.我们可以用Socket来创建客户端 /***类名 Client*描述 TODO 客户端 1*版本 1.0*创建人 XuKang*创建时间 2020/9/24 16:18**/ public class Client {public static void main(String[] args) throws UnknownHostException, IOException {System.out.println(…

Java在线聊天室(客户端+服务器)

Java在线聊天室&#xff08;客户端服务器&#xff09;基于webSocket实现模拟在线聊天系统 运行环境&#xff1a; JDK1.8version 开发环境&#xff1a;Eclipse 一、结构 以下是系统主要结构&#xff1a; 1.用户&#xff08;均实现部分可能会有bug&#xff09; &#xff08;…

apiDay09整理笔记(笔记优化)

目录 1.聊天室&#xff08;续&#xff09; &#xff08;1&#xff09;实现服务端发送消息给客户端 &#xff08;2&#xff09;服务端转发消息给所有客户端 &#xff08;3&#xff09;客户端解决收发消息的冲突问题 &#xff08;4&#xff09;服务端完成处理客户端断开连接…

JAVA简单聊天室的实现

目录 界面效果图 一、聊天室功能介绍&#xff1f; 二、功能代码 1.服务端 2.客户端 界面效果图 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、聊天室功能介绍&#xff1f; 1. 、对于聊天室就是处理多个客户端发送的请求与信息&#xff0c;从…

Java网络聊天室---个人博客

Java网络聊天室 ———个人博客 一、项目简介 功能描述&#xff1a; 使用图形用户界面和socket通信&#xff0c;能实现一个聊天室中多人聊天&#xff0c;可以两人私聊&#xff0c;可以发送文件。 实现类似QQ用户注册、登录、聊天等功能。 参考git地址或博客地址&#xff1a…

Java实现ChatRoom

基于连接通信Socket、多线程的Java聊天室 1、开发环境&#xff1a; IDEA2018.1JDK1.8 2、实现功能&#xff1a; 实现了模拟登录注册、群聊、私聊、显示当前在线人数列表&#xff1b; 在发送信息时&#xff0c;会向对方发送者及显示发送时间&#xff1b; 显示在线人数列表…

Java聊天室

项目介绍&#xff1a; Java聊天室是期末设计&#xff0c; 阿里巴巴druidmysql多线程GUImvn项目java Socket 服务端模块&#xff1a;踢出聊天室&#xff1a;管理员可以踢出发言不当的用户。只有当开启服务端的时候&#xff0c;客户端才能起到作用。 客户端模块&#xff1a; 注册…

用Java实现简易聊天室

说明&#xff1a;如果一个 类&#xff0c;需要有界面的显示&#xff0c;那么该类就需要继承自JFrame&#xff0c;此时&#xff0c;该类就可以被称为一个“窗体类"。 服务端代码&#xff1a; package cn.qy.chat;import javax.swing.*; import java.awt.*; import java.aw…

微信小程序购物车功能实现(干货满满)

微信小程序定制好看的购物车页面&#xff0c;实现购物车功能&#xff0c;希望对您有所帮助&#xff01; 1. 应用场景 2. 思路分析 3. 代码分析 4. 具体实现代码 效果截图&#xff1a; 1.应用场景 适用于商城、秒杀、商品购买等类型的小程序&#xff0c;负责将顾客浏览的商…

微信小程序微商城(八):缓存实现商品购物车功能

IT实战联盟博客&#xff1a;http://blog.100boot.cn 上一篇&#xff1a;微信小程序微商城&#xff08;七&#xff09;&#xff1a;动态API实现商品分类 看效果 购物车.gif 开发计划 1、商品详情页将商品信息放入缓存 2、购物车页面读取缓存获取商品信息 3、购物车商品计算…

微信小程序开发一个小型商城(六、购物车页面)

上一篇文章&#xff1a;微信小程序开发一个小型商城&#xff08;五、商品详情&#xff09; 当我们在商品详情界面中点击添加购物后&#xff0c;会跳转到购物车界面&#xff0c;购物车界面是一个tabbar&#xff0c;在跳转的时候需要加上ope-type。看下购物车的静态页面把&#x…

微信小程序实现一个购物车页面的简易列表效果

本文只是简单的模仿天猫APP的购物车列表的样式效果&#xff0c;并实现了部分事件功能&#xff0c;功能并不完善&#xff0c;请降低期待观看。 天猫APP的购物车效果&#xff1a; 小程序模仿的实现效果&#xff1a; wxml部分的代码&#xff1a; <view wx:if"{{!isCartEmp…

【Python之pymysql库学习】一、分析fetchone()、fetchmany()、fetchall()(保姆级图文+实现代码)

目录 实现效果实现思路实现代码总结 欢迎关注 『Python之pymysql库学习』 系列&#xff0c;持续更新中 欢迎关注 『Python之pymysql库学习』 系列&#xff0c;持续更新中 实现效果 实现思路 其实有半数代码是创建数据库和创建数据表并插入数据这些环境配置部分我都写好了&…

fetchone、fetchall

fetchone(): 该方法获取下一个查询结果集。结果集是一个对象,读取一行结果&#xff0c;读取完指向下一行&#xff0c;到空为止 fetchall():接收全部的返回结果行&#xff0c;到空为止 fetchone() &#xff1a; 返回单个的元组&#xff0c;也就是一条记录(row)&#xff0c;如果没…