亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在Java中利用GUI編程實現在線聊天室

發布時間:2021-05-27 17:14:48 來源:億速云 閱讀:501 作者:Leah 欄目:編程語言

這篇文章將為大家詳細講解有關怎么在Java中利用GUI編程實現在線聊天室,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

客戶端的功能主要包括如下的功能:

  • 選擇連上服務端

  • 顯示當前房間列表(包括房間號和房間名稱)

  • 選擇房間進入

  • 多個用戶在線群聊

  • 可以發送表情(用本地的,實際上發送只發送表情的代碼)

  • 退出房間

  • 選擇創建房間

  • 房間里沒人(房主退出),導致房間解散

  • 顯示系統提示消息

  • 顯示用戶消息

  • 構造標準的消息結構發送

  • 維護GUI所需的數據模型

服務端的功能主要包括:

  • 維護用戶信息和房間信息

  • 處理用戶發送來的消息選擇轉發或者回復處理結果

  • 構造標準的消息結構發送

架構

整個程序采用C/S設計架構,分為一個服務端和多個客戶端。服務端開放一個端口給所有開客戶端,客戶端連接該端口并收發信息,服務端在內部維護客戶端的組,并對每一個客戶端都用一個子線程來收發信息

基本類的設計

User類

package User;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

/**
 * 
 * @author lannooo
 *
 */
public class User {
 private String name;
 private long id;
 private long roomId;
 private Socket socket;
 private BufferedReader br;
 private PrintWriter pw;

 /**
  * 
  * @param name: 設置user的姓名
  * @param id:設置user的id
  * @param socket:保存用戶連接的socket
  * @throws IOException
  */
 public User(String name, long id, final Socket socket) throws IOException {
  this.name=name;
  this.id=id;
  this.socket=socket;
  this.br=new BufferedReader(new InputStreamReader(
    socket.getInputStream()));
  this.pw=new PrintWriter(socket.getOutputStream());

 }

 /**
  * 獲得該用戶的id
  * @return id
  */
 public long getId() {
  return id;
 }

 /**
  * 設置該用戶的id
  * @param id 新的id
  */
 public void setId(long id) {
  this.id = id;
 }

 /**
  * 獲得用戶當前所在的房間號
  * @return roomId
  */
 public long getRoomId() {
  return roomId;
 }

 /**
  * 設置當前用戶的所在的房間號
  * @param roomId
  */
 public void setRoomId(long roomId) {
  this.roomId = roomId;
 }

 /**
  * 設置當前用戶在聊天室中的昵稱
  * @param name
  */
 public void setName(String name) {
  this.name = name;
 }

 /**
  * 返回當前用戶在房間中的昵稱
  * @return
  */
 public String getName() {
  return name;
 }

 /**
  * 返回當前用戶連接的socket實例
  * @return
  */
 public Socket getSocket() {
  return socket;
 }

 /**
  * 設置當前用戶連接的socket
  * @param socket
  */
 public void setSocket(Socket socket) {
  this.socket = socket;
 }

 /**
  * 獲得該用戶的消息讀取輔助類BufferedReader實例
  * @return
  */
 public BufferedReader getBr() {
  return br;
 }

 /**
  * 設置 用戶的消息讀取輔助類
  * @param br
  */
 public void setBr(BufferedReader br) {
  this.br = br;
 }

 /**
  * 獲得消息寫入類實例
  * @return
  */
 public PrintWriter getPw() {
  return pw;
 }

 /**
  * 設置消息寫入類實例
  * @param pw
  */
 public void setPw(PrintWriter pw) {
  this.pw = pw;
 }

 /**
  * 重寫了用戶類打印的函數
  */
 @Override
 public String toString() {
  return "#User"+id+"#"+name+"[#Room"+roomId+"#]<socket:"+socket+">";
 }
}

Room類

package Room;

import java.util.ArrayList;
import java.util.List;

import User.User;

/**
 * 
 * @author lannooo
 *
 */
public class Room {
 private String name;
 private long roomId;
 private ArrayList<User> list;
 private int totalUsers;

 /**
  * 獲得房間的名字
  * @return name
  */
 public String getName() {
  return name;
 }

 /**
  * 設置房間的新名字
  * @param name
  */
 public void setName(String name) {
  this.name = name;
 }

 /**
  * 獲得房間的id號
  * @return
  */
 public long getRoomId() {
  return roomId;
 }

 /**
  * 設置房間的id
  * @param roomId
  */
 public void setRoomId(long roomId) {
  this.roomId = roomId;
 }

 /**
  * 向房間中加入一個新用戶
  * @param user
  */
 public void addUser(User user) {
  if(!list.contains(user)){
   list.add(user);
   totalUsers++;
  }else{
   System.out.println("User is already in Room<"+name+">:"+user);
  }
 }

 /**
  * 從房間中刪除一個用戶
  * @param user
  * @return 目前該房間中的總用戶數目
  */
 public int delUser(User user){
  if(list.contains(user)){
   list.remove(user);
   return --totalUsers;
  }else{
   System.out.println("User is not in Room<"+name+">:"+user);
   return totalUsers;
  }
 }

 /**
  * 獲得當前房間的用戶列表
  * @return
  */
 public ArrayList<User> getUsers(){
  return list;
 }

 /**
  * 獲得當前房間的用戶昵稱的列表
  * @return
  */
 public String[] getUserNames(){
  String[] userList = new String[list.size()];
  int i=0;
  for(User each: list){
   userList[i++]=each.getName();
  }
  return userList;
 }

 /**
  * 使用房間的名稱和id來new一個房間
  * @param name
  * @param roomId
  */
 public Room(String name, long roomId) {
  this.name=name;
  this.roomId=roomId;
  this.totalUsers=0;
  list = new ArrayList<>();
 }
}

RoomList類

package Room;

import java.awt.image.DirectColorModel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import User.User;

/**
 * 
 * @author lannooo
 *
 */
public class RoomList {
 private HashMap<Long, Room> map;
 private long unusedRoomId;
 public static long MAX_ROOMS = 9999;
 private int totalRooms;

 /**
  * 未使用的roomid從1算起,起始的房間總數為0
  */
 public RoomList(){
  map = new HashMap<>();
  unusedRoomId = 1;
  totalRooms = 0;
 }

 /**
  * 創建一個新的房間,使用未使用的房間號進行創建,如果沒有可以使用的則就創建失敗
  * @param name: 房間的名字
  * @return 創建的房間的id
  */
 public long createRoom(String name){
  if(totalRooms<MAX_ROOMS){
   if(name.length()==0){
    name = ""+unusedRoomId;
   }
   Room room = new Room(name, unusedRoomId);
   map.put(unusedRoomId, room);
   totalRooms++;
   return unusedRoomId++;
  }else{
   return -1;
  }
 }
 /**
  * 用戶加入一個房間
  * @param user
  * @param roomID
  * @return
  */
 public boolean join(User user, long roomID){
  if(map.containsKey(roomID)){
   map.get(roomID).addUser(user);
   return true;
  }else{
   return false;
  }
 }

 /**
  * 用戶退出他的房間
  * @param user
  * @param roomID
  * @return
  */
 public int esc(User user, long roomID){
  if(map.containsKey(roomID)){
   int number = map.get(roomID).delUser(user);
   /*如果這個房間剩下的人數為0,那么刪除該房間*/
   if(number==0){
    map.remove(roomID);
    totalRooms--;
    return 0;
   }
   return 1;
  }else{
   return -1;
  }
 }
 /**
  * 列出所有房間的列表,返回一個二維數組,strings[i][0]放房間的id,string[i][1]放房間的name
  * @return
  */
 public String[][] listRooms(){
  String[][] strings = new String[totalRooms][2];
  int i=0;
  /*將map轉化為set并使用迭代器來遍歷*/
  Set<Entry<Long, Room>> set = map.entrySet();
  Iterator<Entry<Long, Room>> iterator = set.iterator();
  while(iterator.hasNext()){
   Map.Entry<Long, Room> entry = iterator.next();
   long key = entry.getKey();
   Room value = entry.getValue();
   strings[i][0]=""+key;
   strings[i][1]=value.getName();
  }
  return strings;
 }

 /**
  * 通過roomID來獲得房間
  * @param roomID
  * @return
  */
 public Room getRoom(long roomID){
  if(map.containsKey(roomID)){
   return map.get(roomID);
  }
  else 
   return null;
 }
}

服務端

Server

package Server;

import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.json.*;

import Room.Room;
import Room.RoomList;
import User.User;
/**
 * 
 * @author lannooo
 *
 */
public class Server {
 private ArrayList<User> allUsers;
 private RoomList rooms;
 private int port;
 private ServerSocket ss;
 private long unusedUserID;
 public final long MAX_USERS = 999999;

 /**
  * 通過port號來構造服務器端對象
  * 維護一個總的用戶列表和一個房間列表
  * @param port
  * @throws Exception
  */
 public Server(int port) throws Exception {
  allUsers = new ArrayList<>();
  rooms = new RoomList();
  this.port=port;
  unusedUserID=1;
  ss = new ServerSocket(port);
  System.out.println("Server is builded!");
 }

 /**
  * 獲得下一個可用的用戶id
  * @return
  */
 private long getNextUserID(){
  if(unusedUserID < MAX_USERS)
   return unusedUserID++;
  else
   return -1;
 }

 /**
  * 開始監聽,當接受到新的用戶連接,就創建一個新的用戶,并添加到用戶列表中
  * 然后創建一個新的服務線程用于收發該用戶的消息
  * @throws Exception
  */
 public void startListen() throws Exception{
  while(true){
   Socket socket = ss.accept();
   long id = getNextUserID();
   if(id != -1){
    User user = new User("User"+id, id, socket);
    System.out.println(user.getName() + " is login...");
    allUsers.add(user);
    ServerThread thread = new ServerThread(user, allUsers, rooms);
    thread.start();
   }else{
    System.out.println("Server is full!");
    socket.close();
   }
  }
 }

 /**
  * 測試用main方法,設置偵聽端口為9999,并開始監聽
  * @param args
  */
 public static void main(String[] args) {
  try {
   Server server = new Server(9999);
   server.startListen();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}

ServerThread

package Server;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import Room.Room;
import Room.RoomList;
import User.User;

/**
 * 
 * @author lannooo
 *
 */
public class ServerThread extends Thread {
 private User user;
 private ArrayList<User> userList;/*保存用戶列表*/
 private RoomList map;   /*保存房間列表*/
 private long roomId;
 private PrintWriter pw;
 /**
  * 通過用戶的對象實例、全局的用戶列表、房間列表進行構造
  * @param user
  * @param userList
  * @param map
  */
 public ServerThread(User user, 
   ArrayList<User> userList, RoomList map){
  this.user=user;
  this.userList=userList;
  this.map=map;
  pw=null;
  roomId = -1;
 }

 /**
  * 線程運行部分,持續讀取用戶socket發送來的數據,并解析
  */
 public void run(){
  try{
   while (true) {
    String msg=user.getBr().readLine();
    System.out.println(msg); /*解析用戶的數據格式*/
    parseMsg(msg);
   }
  }catch (SocketException se) { /*處理用戶斷開的異常*/
   System.out.println("user "+user.getName()+" logout.");

  }catch (Exception e) { /*處理其他異常*/
   e.printStackTrace();
  }finally {
   try {
    /*
     * 用戶斷開或者退出,需要把該用戶移除
     * 并關閉socket
     */
    remove(user);
    user.getBr().close();
    user.getSocket().close();
   } catch (IOException ioe) {
    ioe.printStackTrace();
   }
  }
 }

 /**
  * 用正則表達式匹配數據的格式,根據不同的指令類型,來調用相應的方法處理
  * @param msg
  */
 private void parseMsg(String msg){
  String code = null;
  String message=null;
  if(msg.length()>0){
   /*匹配指令類型部分的字符串*/
   Pattern pattern = Pattern.compile("<code>(.*)</code>");
   Matcher matcher = pattern.matcher(msg);
   if(matcher.find()){
    code = matcher.group(1);
   }
   /*匹配消息部分的字符串*/
   pattern = Pattern.compile("<msg>(.*)</msg>");
   matcher = pattern.matcher(msg);
   if(matcher.find()){
    message = matcher.group(1);
   }

   switch (code) {
   case "join":
    // add to the room
    // code = 1, 直接顯示在textArea中
    // code = 11, 在list中加入
    // code = 21, 把當前房間里的所有用戶返回給client
    if(roomId == -1){
     roomId = Long.parseLong(message);
     map.join(user, roomId);
     sendRoomMsgExceptSelf(buildCodeWithMsg("<name>"+user.getName()+"</name><id>"+user.getId()+"</id>", 11));
     // 這個消息需要加入房間里已有用戶的列表
     returnMsg(buildCodeWithMsg("你加入了房間:" + map.getRoom(roomId).getName(), 1));
     returnMsg(buildCodeWithMsg(getMembersInRoom(), 21));
    }else{
     map.esc(user, roomId);
     sendRoomMsg(buildCodeWithMsg(""+user.getId(), 12));
     long oldRoomId = roomId;
     roomId = Long.parseLong(message);
     map.join(user, roomId);
     sendRoomMsgExceptSelf(buildCodeWithMsg("<name>"+user.getName()+"</name><id>"+user.getId()+"</id>", 11));
     returnMsg(buildCodeWithMsg("你退出房間:" + map.getRoom(oldRoomId).getName() + ",并加入了房間:" + roomId,1));
     returnMsg(buildCodeWithMsg(getMembersInRoom(), 21));
    }
    break;
   case "esc":
    // delete from room list
    // code = 2, 彈窗提示
    // code = 12, 對所有該房間的其他用戶發送該用戶退出房間的信息,從list中刪除
    if(roomId!=-1){
     int flag=map.esc(user, roomId);
     sendRoomMsgExceptSelf(buildCodeWithMsg(""+user.getId(), 12));
     long oldRoomId=roomId;
     roomId = -1;
     returnMsg(buildCodeWithMsg("你已經成功退出房間,不會收到消息", 2));
     if(flag==0){
      sendMsg(buildCodeWithMsg(""+oldRoomId, 13));
     }
    }else{
     returnMsg(buildCodeWithMsg("你尚未加入任何房間", 2));
    }
    break;
   case "list":
    // list all the rooms
    // code = 3, 在客戶端解析rooms,并填充roomlist
    returnMsg(buildCodeWithMsg(getRoomsList(), 3));
    break;
   case "message":
    // send message
    // code = 4, 自己收到的話,打印的是‘你說:....'否則打印user id對應的name
    sendRoomMsg(buildCodeWithMsg("<from>"+user.getId()+"</from><smsg>"+message+"</smsg>", 4));
    break;
   case "create":
    // create a room 
    // code=5,提示用戶進入了房間
    // code=15,需要在其他所有用戶的room列表中更新
    roomId = map.createRoom(message);
    map.join(user, roomId);
    sendMsg(buildCodeWithMsg("<rid>"+roomId+"</rid><rname>"+message+"</rname>", 15));
    returnMsg(buildCodeWithMsg("你進入了創建的房間:"+map.getRoom(roomId).getName(), 5));
    returnMsg(buildCodeWithMsg(getMembersInRoom(), 21));
    break;
   case "setname":
    // set name for user
    // code=16,告訴房間里的其他人,你改了昵稱
    user.setName(message);
    sendRoomMsg(buildCodeWithMsg("<id>"+user.getId()+"</id><name>"+message+"</name>", 16));
    break;
   default:
    // returnMsg("something unknown");
    System.out.println("not valid message from user"+user.getId());
    break;
   }
  } 
 }

 /**
  * 獲得該用戶房間中的所有用戶列表,并構造成一定格式的消息返回
  * @return
  */
 private String getMembersInRoom(){
  /*先從room列表獲得該用戶的room*/
  Room room = map.getRoom(roomId);
  StringBuffer stringBuffer = new StringBuffer();
  if(room != null){
   /*獲得房間中所有的用戶的列表,然后構造成一定的格式發送回去*/
   ArrayList<User> users = room.getUsers();
   for(User each: users){
    stringBuffer.append("<member><name>"+each.getName()+
        "</name><id>"+each.getId()+"</id></member>");
   }
  }
  return stringBuffer.toString();
 }

 /**
  * 獲得所有房間的列表,并構造成一定的格式
  * @return
  */
 private String getRoomsList(){
  String[][] strings = map.listRooms();
  StringBuffer sb = new StringBuffer();
  for(int i=0; i<strings.length; i++){
   sb.append("<room><rname>"+strings[i][1]+
      "</rname><rid>"+strings[i][0]+"</rid></room>");
  }
  return sb.toString();
 }

 /**
  * 構造成一個統一的消息格式
  * @param msg
  * @param code
  * @return
  */
 private String buildCodeWithMsg(String msg, int code){
  return "<code>"+code+"</code><msg>"+msg+"</msg>\n";
 }

 /**
  * 這個是群發消息:全體用戶,code>10
  * @param msg
  */
 private void sendMsg(String msg) {
//  System.out.println("In sendMsg()");
  /*取出用戶列表中的每一個用戶來發送消息*/
  for(User each:userList){
   try {
    pw=each.getPw();
    pw.println(msg);
    pw.flush();
    System.out.println(msg);
   } catch (Exception e) {
    System.out.println("exception in sendMsg()");
   }
  }
 }

 /**
  * 只對同一房間的用戶發:code>10
  * @param msg
  */
 private void sendRoomMsg(String msg){
  /*先獲得該用戶的房間號,然后往該房間發送消息*/
  Room room = map.getRoom(roomId);
  if(room != null){
   ArrayList<User> users = room.getUsers();
   for(User each: users){
    pw = each.getPw();
    pw.println(msg);
    pw.flush();
   }
  }
 }
 /**
  * 向房間中除了該用戶自己,發送消息
  * @param msg
  */
 private void sendRoomMsgExceptSelf(String msg){
  Room room = map.getRoom(roomId);
  if(room != null){
   ArrayList<User> users = room.getUsers();
   for(User each: users){
    if(each.getId()!=user.getId()){
     pw = each.getPw();
     pw.println(msg);
     pw.flush();
    }
   }
  }
 }

 /**
  * 對于client的來信,返回一個結果,code<10
  * @param msg
  */
 private void returnMsg(String msg){
  try{
   pw = user.getPw();
   pw.println(msg);
   pw.flush();
  }catch (Exception e) {
   System.out.println("exception in returnMsg()");
  }
 }

 /**
  * 移除該用戶,并向房間中其他用戶發送該用戶已經退出的消息
  * 如果房間中沒人了,那么就更新房間列表給所有用戶
  * @param user
  */
 private void remove(User user){
  if(roomId!=-1){
   int flag=map.esc(user, roomId);
   sendRoomMsgExceptSelf(buildCodeWithMsg(""+user.getId(), 12));
   long oldRoomId=roomId;
   roomId = -1;
   if(flag==0){
    sendMsg(buildCodeWithMsg(""+oldRoomId, 13));
   }
  }
  userList.remove(user);
 }
}

客戶端

Client

package Client;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;


/**
 * 
 * @author lannooo
 *
 */
public class Client implements ActionListener{
 private JFrame frame;
 private Socket socket;
 private BufferedReader br;
 private PrintWriter pw;
 private String name;
 private HashMap<String, Integer> rooms_map;
 private HashMap<String, Integer> users_map;
 private JTextField host_textfield;
 private JTextField port_textfield;
 private JTextField text_field;
 private JTextField name_textfiled;
 private JLabel rooms_label;
 private JLabel users_label;
 private JList<String> roomlist;
 private JList<String> userlist;
 private JTextPane msgArea;
 private JScrollPane textScrollPane;
 private JScrollBar vertical;
 DefaultListModel<String> rooms_model;
 DefaultListModel<String> users_model;

 /*
  * 構造函數
  * 該客戶端對象維護兩個map,房間的hashmap和房間中用戶的hashmap
  * 作為列表組件的數據模型
  */
 public Client(){
  rooms_map = new HashMap<>();
  users_map = new HashMap<>();
  initialize();
 }

 /**
  * 連接服務端,指定host和port
  * @param host
  * @param port
  * @return
  */
 public boolean connect(String host, int port){
  try {
   socket = new Socket(host, port);
   System.out.println("Connected to server!"+socket.getRemoteSocketAddress());
   br=new BufferedReader(new InputStreamReader(System.in));
   pw=new PrintWriter(socket.getOutputStream());
   /*
    * 創建一個接受和解析服務器消息的線程
    * 傳入當前客戶端對象的指針,作為句柄調用相應的處理函數
    */
   ClientThread thread = new ClientThread(socket, this);
   thread.start();

   return true;

  } catch (IOException e) {
   System.out.println("Server error");
   JOptionPane.showMessageDialog(frame, "服務器無法連接!");
   return false;
  }
 }

 /*當前進程作為只發送消息的線程,從命令行中獲取輸入*/
// public void sendMsg(){
//  String msg;
//  try {
//   while(true){
//    msg = br.readLine();
//    pw.println(msg);
//    pw.flush();
//   }
//  } catch (IOException e) {
//   System.out.println("error when read msg and to send.");
//  }
// }

 /**
  * 發給服務器的消息,先經過一定的格式構造再發送
  * @param msg
  * @param code
  */
 public void sendMsg(String msg, String code){
  try {
   pw.println("<code>"+code+"</code><msg>"+msg+"</msg>");
   pw.flush();
  } catch (Exception e) {
   //一般是沒有連接的問題
   System.out.println("error in sendMsg()");
   JOptionPane.showMessageDialog(frame, "請先連接服務器!");
  }
 }

 /**
  * 窗口初始化
  */
 private void initialize() {
  /*設置窗口的UI風格和字體*/
  setUIStyle();
  setUIFont();

  JFrame frame = new JFrame("ChatOnline");
  JPanel panel = new JPanel();  /*主要的panel,上層放置連接區,下層放置消息區,
             中間是消息面板,左邊是room列表,右邊是當前room的用戶列表*/
  JPanel headpanel = new JPanel(); /*上層panel,用于放置連接區域相關的組件*/
  JPanel footpanel = new JPanel(); /*下層panel,用于放置發送信息區域的組件*/
  JPanel leftpanel = new JPanel(); /*左邊panel,用于放置房間列表和加入按鈕*/
  JPanel rightpanel = new JPanel(); /*右邊panel,用于放置房間內人的列表*/

  /*最上層的布局,分中間,東南西北五個部分*/
  BorderLayout layout = new BorderLayout();
  /*格子布局,主要用來設置西、東、南三個部分的布局*/
  GridBagLayout gridBagLayout = new GridBagLayout();
  /*主要設置北部的布局*/
  FlowLayout flowLayout = new FlowLayout();
  /*設置初始窗口的一些性質*/
  frame.setBounds(100, 100, 800, 600);
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setContentPane(panel);
  frame.setLayout(layout);
  /*設置各個部分的panel的布局和大小*/
  headpanel.setLayout(flowLayout);
  footpanel.setLayout(gridBagLayout);
  leftpanel.setLayout(gridBagLayout);
  rightpanel.setLayout(gridBagLayout);
  leftpanel.setPreferredSize(new Dimension(130, 0));
  rightpanel.setPreferredSize(new Dimension(130, 0));


  /*以下均是headpanel中的組件*/
  host_textfield = new JTextField("127.0.0.1");
  port_textfield = new JTextField("9999");
  name_textfiled = new JTextField("匿名");
  host_textfield.setPreferredSize(new Dimension(100, 25));
  port_textfield.setPreferredSize(new Dimension(70, 25));
  name_textfiled.setPreferredSize(new Dimension(150, 25));

  JLabel host_label = new JLabel("服務器IP");
  JLabel port_label = new JLabel("端口");
  JLabel name_label = new JLabel("昵稱");

  JButton head_connect = new JButton("連接");
//  JButton head_change = new JButton("確認更改");
  JButton head_create = new JButton("創建房間");

  headpanel.add(host_label);
  headpanel.add(host_textfield);
  headpanel.add(port_label);
  headpanel.add(port_textfield);
  headpanel.add(head_connect);
  headpanel.add(name_label);
  headpanel.add(name_textfiled);
//  headpanel.add(head_change);
  headpanel.add(head_create);

  /*以下均是footpanel中的組件*/
  JButton foot_emoji = new JButton("表情");
  JButton foot_send = new JButton("發送");
  text_field = new JTextField();
  footpanel.add(text_field, new GridBagConstraints(0, 0, 1, 1, 100, 100, 
    GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
  footpanel.add(foot_emoji, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0, 
    GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
  footpanel.add(foot_send, new GridBagConstraints(2, 0, 1, 1, 1.0, 1.0, 
    GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));

  /*兩邊的格子中的組件*/
  rooms_label = new JLabel("當前房間數:0");
  users_label = new JLabel("房間內人數:0");
  JButton join_button = new JButton("加入房間");
  JButton esc_button = new JButton("退出房間");

  rooms_model = new DefaultListModel<>();
  users_model = new DefaultListModel<>();
//  rooms_model.addElement("房間1");
//  rooms_model.addElement("房間2");
//  rooms_model.addElement("房間3");
//  String fangjian = "房間1";
//  rooms_map.put(fangjian, 1);

  roomlist = new JList<>(rooms_model);
  userlist = new JList<>(users_model);

  JScrollPane roomListPane = new JScrollPane(roomlist);
  JScrollPane userListPane = new JScrollPane(userlist);

  leftpanel.add(rooms_label, new GridBagConstraints(0, 0, 1, 1, 1, 1, 
    GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
  leftpanel.add(join_button, new GridBagConstraints(0, 1, 1, 1, 1, 1, 
    GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
  leftpanel.add(esc_button, new GridBagConstraints(0, 2, 1, 1, 1, 1, 
    GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
  leftpanel.add(roomListPane, new GridBagConstraints(0, 3, 1, 1, 100, 100, 
    GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
  rightpanel.add(users_label, new GridBagConstraints(0, 0, 1, 1, 1, 1, 
    GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
  rightpanel.add(userListPane,new GridBagConstraints(0, 1, 1, 1, 100, 100, 
    GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));

  /*中間的文本區組件*/
  msgArea = new JTextPane();
  msgArea.setEditable(false);
  textScrollPane = new JScrollPane();
  textScrollPane.setViewportView(msgArea);
  vertical = new JScrollBar(JScrollBar.VERTICAL);
  vertical.setAutoscrolls(true);
  textScrollPane.setVerticalScrollBar(vertical);

  /*設置頂層布局*/
  panel.add(headpanel, "North");
  panel.add(footpanel, "South");
  panel.add(leftpanel, "West");
  panel.add(rightpanel, "East");
  panel.add(textScrollPane, "Center");

  /*注冊各種事件*/
  /*連接服務器*/
  head_connect.addActionListener(this);
  /*發送消息,如果沒有連接則會彈窗提示*/
  foot_send.addActionListener(this);
  /*改名字*/
//  head_change.addActionListener(this);
  /*創建房間*/
  head_create.addActionListener(this);
  /*發送表情*/
  foot_emoji.addActionListener(this);
  /*加入room*/
  join_button.addActionListener(this);
  /*退出房間*/
  esc_button.addActionListener(this);

  /*最終顯示*/
  frame.setVisible(true);
 }

 /**
  * 事件監聽處理
  */
 @Override
 public void actionPerformed(ActionEvent e) {
  String cmd = e.getActionCommand();
  switch (cmd) {
  case "連接": /*點擊連接按鈕*/
   String strhost = host_textfield.getText();
   String strport = port_textfield.getText();
   connect(strhost, Integer.parseInt(strport));
   String nameSeted = JOptionPane.showInputDialog("請輸入你的昵稱:"); /*提示輸入昵稱*/
   name_textfiled.setText(nameSeted);
   name_textfiled.setEditable(false);
   port_textfield.setEditable(false);
   host_textfield.setEditable(false);
   /*發送設置姓名的消息和列出用戶列表的消息*/
   sendMsg(nameSeted, "setname");
   sendMsg("", "list");
   break;
//  case "確認更改":
//   String strname = name_textfiled.getText();
//   name = strname;
//   sendMsg(strname, "setname");
//   break;
  case "加入房間": /*選擇房間后,點擊加入房間按鈕*/
   String selected = roomlist.getSelectedValue();
   if(rooms_map.containsKey(selected)){
    sendMsg(""+rooms_map.get(selected), "join");
   }
   break;
  case "退出房間": /*點擊退出房間的按鈕*/
   sendMsg("", "esc");
   break;
  case "發送":  /*點擊發送消息的按鈕*/
   String text = text_field.getText();
   text_field.setText("");
   sendMsg(text, "message");
   break;
  case "表情":  /*發送表情,新建一個表情窗口,并直接在表情窗口中處理消息發送*/
   IconDialog dialog = new IconDialog(frame, this);
   break;
  case "創建房間": /*點擊創建房間的按鈕,彈出提示框數據房間名稱*/
   String string = JOptionPane.showInputDialog("請輸入你的房間名稱");
   if(string==null || string.equals("")){
    string = name+(int)(Math.random()*10000)+"的房間";
   }
   sendMsg(string, "create");
   break;
  default:
   break;
  }

 }


 /*很多輔助和clientThread互動的*/

 /**
  * 加入用戶,通過正則表達式,匹配消息內容中的用戶信息
  * @param content
  */
 public void addUser(String content){
  if(content.length()>0){
   Pattern pattern = Pattern.compile("<name>(.*)</name><id>(.*)</id>");
   Matcher matcher = pattern.matcher(content);
   if(matcher.find()){
    /*
     * 獲得用戶的name和id
     * 加入用戶列表
     * 在消息區顯示系統提示
     */
    String name = matcher.group(1);
    String id = matcher.group(2);
    insertUser(Integer.parseInt(id), name);
    insertMessage(textScrollPane, msgArea, null, "系統:", name+"加入了聊天室");
   }
  }
  users_label.setText("房間內人數:"+users_map.size()); /*更新房間內的人數*/
 }

 /**
  * 刪除用戶
  * @param content
  */
 public void delUser(String content){
  if(content.length()>0){
   int id = Integer.parseInt(content);
   /*
    * 從維護的用戶map中取得所有的用戶名字,然后去遍歷匹配的用戶
    * 匹配到的用戶名字從相應的數據模型中移除
    * 并從map中移除,并在消息框中提示系統消息
    */
   Set<String> set = users_map.keySet();
   Iterator<String> iter = set.iterator();
   String name=null;
   while(iter.hasNext()){
    name = iter.next();
    if(users_map.get(name)==id){
     users_model.removeElement(name);
     break;
    }
   }
   users_map.remove(name);
   insertMessage(textScrollPane, msgArea, null, "系統:", name+"退出了聊天室");
  }
  users_label.setText("房間內人數:"+users_map.size());
 }


 /**
  * 更新用戶信息
  * @param content
  */
 public void updateUser(String content){
  if(content.length()>0){
   Pattern pattern = Pattern.compile("<id>(.*)</id><name>(.*)</name>");
   Matcher matcher = pattern.matcher(content);
   if(matcher.find()){
    String id = matcher.group(1);
    String name = matcher.group(2);
    insertUser(Integer.parseInt(id), name);
   }
  }
 }

 /**
  * 列出所有用戶
  * @param content
  */
 public void listUsers(String content){
  String name = null;
  String id=null;
  Pattern rough_pattern=null;
  Matcher rough_matcher=null;
  Pattern detail_pattern=null;
  /*
   * 先用正則表達式匹配用戶信息
   * 然后插入數據模型中
   * 并更新用戶數據模型中的條目
   */
  if(content.length()>0){
   rough_pattern = Pattern.compile("<member>(.*?)</member>");
   rough_matcher = rough_pattern.matcher(content);
   while(rough_matcher.find()){
    String detail = rough_matcher.group(1);
    detail_pattern = Pattern.compile("<name>(.*)</name><id>(.*)</id>");
    Matcher detail_matcher = detail_pattern.matcher(detail);
    if(detail_matcher.find()){
     name = detail_matcher.group(1);
     id = detail_matcher.group(2);
     insertUser(Integer.parseInt(id), name);
    }
   }
  }
  users_label.setText("房間內人數:"+users_map.size());
 }

 /**
  * 直接在textarea中顯示消息
  * @param content
  */
 public void updateTextArea(String content){
  insertMessage(textScrollPane, msgArea, null, "系統:", content);
 }

 /**
  * 在textarea中顯示其他用戶的消息
  * 先用正則匹配,再顯示消息
  * 其中還需要匹配emoji表情的編號
  * @param content
  */
 public void updateTextAreaFromUser(String content){
  if(content.length()>0){
   Pattern pattern = Pattern.compile("<from>(.*)</from><smsg>(.*)</smsg>");
   Matcher matcher = pattern.matcher(content);
   if(matcher.find()){
    String from = matcher.group(1);
    String smsg = matcher.group(2);
    String fromName = getUserName(from);
    if(fromName.equals(name))
     fromName = "你";
    if(smsg.startsWith("<emoji>")){
     String emojiCode = smsg.substring(7, smsg.length()-8);
//     System.out.println(emojiCode);
     insertMessage(textScrollPane, msgArea, emojiCode, fromName+"說:", null);
     return ;
    }
    insertMessage(textScrollPane, msgArea, null, fromName+"說:", smsg);
   }
  }
 }

 /**
  * 顯示退出的結果
  * @param content
  */
 public void showEscDialog(String content){
  JOptionPane.showMessageDialog(frame, content);
  /*清除消息區內容,清除用戶數據模型內容和用戶map內容,更新房間內人數*/
  msgArea.setText("");
  users_model.clear();
  users_map.clear();
  users_label.setText("房間內人數:0");

 }
 /**
  * 新增一個room
  * @param content
  */
 public void addRoom(String content){
  if(content.length()>0){
   Pattern pattern = Pattern.compile("<rid>(.*)</rid><rname>(.*)</rname>");
   Matcher matcher = pattern.matcher(content);
   if(matcher.find()){
    String rid = matcher.group(1);
    String rname = matcher.group(2);
    insertRoom(Integer.parseInt(rid), rname);
   }
  }
  rooms_label.setText("當前房間數:"+rooms_map.size());
 }

 /**
  * 刪除一個room
  * @param content
  */
 public void delRoom(String content){
  if(content.length()>0){
   int delRoomId = Integer.parseInt(content);

   Set<String> set = rooms_map.keySet();
   Iterator<String> iter = set.iterator();
   String rname=null;
   while(iter.hasNext()){
    rname = iter.next();
    if(rooms_map.get(rname)==delRoomId){
     rooms_model.removeElement(rname);
     break;
    }
   }
   rooms_map.remove(rname);
  }
  rooms_label.setText("當前房間數:"+rooms_map.size());
 }

 /**
  * 列出目前所有的rooms
  * @param content
  */
 public void listRooms(String content){
  String rname = null;
  String rid=null;
  Pattern rough_pattern=null;
  Matcher rough_matcher=null;
  Pattern detail_pattern=null;
  if(content.length()>0){
   rough_pattern = Pattern.compile("<room>(.*?)</room>");
   rough_matcher = rough_pattern.matcher(content);
   while(rough_matcher.find()){
    String detail = rough_matcher.group(1);
    detail_pattern = Pattern.compile("<rname>(.*)</rname><rid>(.*)</rid>");
    Matcher detail_matcher = detail_pattern.matcher(detail);
    if(detail_matcher.find()){
     rname = detail_matcher.group(1);
     rid = detail_matcher.group(2);
     insertRoom(Integer.parseInt(rid), rname);
    }
   }
  }
  rooms_label.setText("當前房間數:"+rooms_map.size());
 }
 /**
  * 插入一個room
  * @param rid
  * @param rname
  */
 private void insertRoom(Integer rid, String rname){
  if(!rooms_map.containsKey(rname)){
   rooms_map.put(rname, rid);
   rooms_model.addElement(rname);
  }else{
   rooms_map.remove(rname);
   rooms_model.removeElement(rname);
   rooms_map.put(rname, rid);
   rooms_model.addElement(rname);
  }
  rooms_label.setText("當前房間數:"+rooms_map.size());
 }
 /**
  * 插入一個user
  * @param id
  * @param name
  */
 private void insertUser(Integer id, String name){
  if(!users_map.containsKey(name)){
   users_map.put(name, id);
   users_model.addElement(name);
  }else{
   users_map.remove(name);
   users_model.removeElement(name);
   users_map.put(name, id);
   users_model.addElement(name);
  }
  users_label.setText("房間內人數:"+users_map.size());
 }

 /**
  * 獲得用戶的姓名
  * @param strId
  * @return
  */
 private String getUserName(String strId){
  int uid = Integer.parseInt(strId);
  Set<String> set = users_map.keySet();
  Iterator<String> iterator = set.iterator();
  String cur=null;
  while(iterator.hasNext()){
   cur = iterator.next();
   if(users_map.get(cur)==uid){
    return cur;
   }
  }
  return "";
 }

 /**
  * 獲得用戶所在房間的名稱
  * @param strId
  * @return
  */
 private String getRoomName(String strId){
  int rid = Integer.parseInt(strId);
  Set<String> set = rooms_map.keySet();
  Iterator<String> iterator = set.iterator();
  String cur = null;
  while(iterator.hasNext()){
   cur = iterator.next();
   if(rooms_map.get(cur)==rid){
    return cur;
   }
  }
  return "";
 }

 /**
  * 打印一條消息,如果有圖片就打印圖片,否則打印content
  * @param scrollPane
  * @param textPane
  * @param icon_code
  * @param title
  * @param content
  */
 private void insertMessage(JScrollPane scrollPane, JTextPane textPane,
   String icon_code, String title, String content){
  StyledDocument document = textPane.getStyledDocument();  /*獲取textpane中的文本*/
  /*設置標題的屬性*/
  SimpleAttributeSet title_attr = new SimpleAttributeSet();
  StyleConstants.setBold(title_attr, true);
  StyleConstants.setForeground(title_attr, Color.BLUE);
  /*設置正文的屬性*/
  SimpleAttributeSet content_attr = new SimpleAttributeSet(); 
  StyleConstants.setBold(content_attr, false); 
  StyleConstants.setForeground(content_attr, Color.BLACK);
  Style style = null;
  if(icon_code!=null){
   Icon icon = new ImageIcon("icon/"+icon_code+".png");
   style = document.addStyle("icon", null); 
   StyleConstants.setIcon(style, icon);
  }

  try { 
   document.insertString(document.getLength(), title+"\n", title_attr);
   if(style!=null)
    document.insertString(document.getLength(), "\n", style);
   else
    document.insertString(document.getLength(), " "+content+"\n", content_attr);

  } catch (BadLocationException ex) { 
   System.out.println("Bad location exception");
  }
  /*設置滑動條到最后*/
  vertical.setValue(vertical.getMaximum());
 }

 /**
  * 設置需要美化字體的組件
  */
 public static void setUIFont()
 {
  Font f = new Font("微軟雅黑", Font.PLAIN, 14);
  String names[]={ "Label", "CheckBox", "PopupMenu","MenuItem", "CheckBoxMenuItem",
    "JRadioButtonMenuItem","ComboBox", "Button", "Tree", "ScrollPane",
    "TabbedPane", "EditorPane", "TitledBorder", "Menu", "TextArea","TextPane",
    "OptionPane", "MenuBar", "ToolBar", "ToggleButton", "ToolTip",
    "ProgressBar", "TableHeader", "Panel", "List", "ColorChooser",
    "PasswordField","TextField", "Table", "Label", "Viewport",
    "RadioButtonMenuItem","RadioButton", "DesktopPane", "InternalFrame"
  }; 
  for (String item : names) {
    UIManager.put(item+ ".font",f); 
  }
 }
 /**
  * 設置UI風格為當前系統的風格
  */
 public static void setUIStyle(){
  String lookAndFeel =UIManager.getSystemLookAndFeelClassName();
  try {
   UIManager.setLookAndFeel(lookAndFeel);
  } catch (ClassNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (InstantiationException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IllegalAccessException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (UnsupportedLookAndFeelException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

 /**
  * 測試用的main函數
  * @param args
  */
 public static void main(String[] args) {
  Client client = new Client();
 }


}

ClientThread

package Client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * 
 * @author lannooo
 *
 */
public class ClientThread extends Thread{
 private Socket socket;
 private Client client;
 private BufferedReader br;
 private PrintWriter pw;
 /**
  * 從過主線程傳入的socket和client對象來構造
  * @param socket
  * @param client
  */
 public ClientThread(Socket socket, Client client){
  this.client = client;
  this.socket = socket;
  try {
   br=new BufferedReader(new InputStreamReader(socket.getInputStream()));

  } catch (IOException e) {
   System.out.println("cannot get inputstream from socket.");
  }
 }

 /**
  * 不斷的讀數據并處理
  * 調用主線程的方法來處理:client.method();
  */
 public void run() {
  try{
   br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
   while(true){
    String msg = br.readLine();
    parseMessage(msg);
   }
  }catch (Exception e) {
   e.printStackTrace();
  }
 }
 /**
  * 處理從服務器收到的消息
  * @param message
  */
 public void parseMessage(String message){
  String code = null;
  String msg=null;
  /*
   * 先用正則表達式匹配code碼和msg內容 
   */
  if(message.length()>0){
   Pattern pattern = Pattern.compile("<code>(.*)</code>");
   Matcher matcher = pattern.matcher(message);
   if(matcher.find()){
    code = matcher.group(1);
   }
   pattern = Pattern.compile("<msg>(.*)</msg>");
   matcher = pattern.matcher(message);
   if(matcher.find()){
    msg = matcher.group(1);
   }
   System.out.println(code+":"+msg);
   switch(code){
   case "1": /*一個普通消息處理*/
    client.updateTextArea(msg);
    break;
   case "2": /*退出消息*/
    client.showEscDialog(msg);
    break;
   case "3": /*列出房間*/
    client.listRooms(msg);
    break;
   case "4": /*其他用戶的消息*/
    client.updateTextAreaFromUser(msg);
    break;
   case "5": /*普通消息處理*/
    client.updateTextArea(msg);
    break;
   case "11": /*添加用戶*/
    client.addUser(msg);
    break;
   case "12": /*刪除用戶*/
    client.delUser(msg);
    break;
   case "13": /*刪除房間*/
    client.delRoom(msg);
    break;
   case "15": /*添加房間*/
    client.addRoom(msg);
    break;
   case "16": /*更新用戶名稱*/
    client.updateUser(msg);
    break;
   case "21": /*列出用戶列表*/
    client.listUsers(msg);
    break;
   }
  }

 }
}

IconDialog(選擇表情界面)

package Client;

import java.awt.Container;
import java.awt.Dialog;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
/**
 * 
 * @author lannooo
 *
 */
public class IconDialog implements ActionListener {

 private JDialog dialog;
 private Client client;
 /**
  * 通過frame和客戶端對象來構造
  * @param frame
  * @param client
  */
 public IconDialog(JFrame frame, Client client) {
  this.client = client;
  dialog = new JDialog(frame, "請選擇表情", true);
  /*16個表情*/
  JButton[] icon_button = new JButton[16];
  ImageIcon[] icons = new ImageIcon[16];
  /*獲得彈出窗口的容器,設置布局*/
  Container dialogPane = dialog.getContentPane();
  dialogPane.setLayout(new GridLayout(0, 4));
  /*加入表情*/
  for(int i=1; i<=15; i++){
   icons[i] = new ImageIcon("icon/"+i+".png");
   icons[i].setImage(icons[i].getImage().getScaledInstance(50, 50, Image.SCALE_DEFAULT));
   icon_button[i] = new JButton(""+i, icons[i]);
   icon_button[i].addActionListener(this);
   dialogPane.add(icon_button[i]);
  }
  dialog.setBounds(200,266,266,280);
  dialog.show();
 }

 @Override
 public void actionPerformed(ActionEvent e) {
  /*構造emoji結構的消息發送*/
  String cmd = e.getActionCommand();
  System.out.println(cmd);
  dialog.dispose();
  client.sendMsg("<emoji>"+cmd+"</emoji>", "message");
 }

}

關于怎么在Java中利用GUI編程實現在線聊天室就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

云安县| 报价| 温州市| 磐石市| 江源县| 山西省| 大洼县| 五家渠市| 汉沽区| 中方县| 集贤县| 河北省| 邵阳市| 正镶白旗| 宣威市| 绥中县| 黄石市| 平遥县| 望城县| 镇安县| 甘南县| 齐河县| 岳池县| 大埔县| 墨竹工卡县| 博客| 张家口市| 东丽区| 阜新市| 溧阳市| 许昌市| 平和县| 新郑市| 吐鲁番市| 双柏县| 原阳县| 高平市| 崇州市| 抚松县| 浏阳市| 顺义区|