100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > Java实现简单的本地QQ聊天系统

Java实现简单的本地QQ聊天系统

时间:2023-06-28 23:44:36

相关推荐

Java实现简单的本地QQ聊天系统

利用Java编写的一个简单的群聊程序,模仿QQ群聊,利用本地通讯,实现了简单的群聊功能。

源码请自取:

csdn资源下载传送门(免费)

程序共分为3个包(先编译运行TerminalServerView.java,再运行LoginView.java):

client包中存放辅助实现客户端功能的类server包中存放辅助实现服务终端功能的类view包中存放界面相关的类

附各模块代码:

目录:

1. client包1.1 package-info.java1.2 Client.java2. server包2.1 package-info.java2.2 UserSupervision.java2.3 TerminalServer.java3. view包3.1 package-info.java3.2 TerminalServerView.java3.3 LoginView.java3.4 ChatView.java3.5 WarningView.java

1. client包

1.1 package-info.java

/*** 提供帮助实现客户端功能的类* * @author JuJunjian* @version 1.0 -11-21*/package com.jujunjian.client;

1.2 Client.java

package com.jujunjian.client;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import .Socket;import .SocketException;import .UnknownHostException;/*** 实现了客户端的功能* * @author JuJunjian* @version 1.0 -11-21*/public class Client {private static final String LOCALHOST = "127.0.0.1";private static final String CHARSET = "UTF-8"; // 编码方式private static final int TERMINAL_PORT = 8888; // 服务端的端口号private Socket socket;private InputStream inputStream;private OutputStream oututStream;/*** 实例化一个客户端对象*/public Client() {try {socket = new Socket(LOCALHOST, TERMINAL_PORT);inputStream = socket.getInputStream();oututStream = socket.getOutputStream();} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}/*** 向服务终端申请账号的请求* * @param id 用户申请的账号,id为0代表申请一个随机的账号*/public void applyId(int id) {byte[] byteId = toByte(id);try {oututStream.write(byteId);oututStream.flush();} catch (IOException e) {e.printStackTrace();}}/*** @return 返回申请账号的结果*/public int getApplyIdResult() {int result = -1;byte[] byteResult = new byte[4];try {inputStream.read(byteResult);result = toInt(byteResult);} catch (IOException e) {e.printStackTrace();}return result;}/*** 调用此方法以发送消息* * @param message 需发送的消息*/public void sendMessage(String message) {try {byte[] byteMessage = message.getBytes(CHARSET);int length = byteMessage.length;byte[] head = toByte(length); // 字节流前的报头,代表了消息字节流的长度,用于辅助接收端判断是否接收完毕// 得到最终被传输的字节流byte[] outByte = new byte[length + head.length];System.arraycopy(head, 0, outByte, 0, head.length);System.arraycopy(byteMessage, 0, outByte, head.length, byteMessage.length);oututStream.write(outByte);oututStream.flush();} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}/*** 用于接收新消息,每次调用只可接收一条新消息* * @return 返回接收到的信息(字符串类型)*/public String startReceiveMessage() {String receiveMessage = "";byte[] head = new byte[4]; // 消息的长度try {inputStream.read(head);int messageLength = toInt(head);byte[] byteMessage = new byte[messageLength];inputStream.read(byteMessage);receiveMessage = new String(byteMessage, CHARSET);} catch (SocketException e) {} catch (IOException e) {e.printStackTrace();}return receiveMessage;}/*** 调用此方法可用结束与服务终端的通讯*/public void endCommunication() {try {int result = -1; // -1 表示结束整个群聊byte[] end = toByte(result); oututStream.write(end);oututStream.flush();socket.close();} catch (IOException e) {e.printStackTrace();}}// 将int类型的数据转换为4位byte类型的数据private byte[] toByte(int intData) {byte[] byteData = new byte[4];byteData[0] = (byte) ((intData >> 24) & 0xFF);byteData[1] = (byte) ((intData >> 16) & 0xFF);byteData[2] = (byte) ((intData >> 8) & 0xFF);byteData[3] = (byte) (intData & 0xFF);return byteData;}// 将4位byte类型的数据转换为int类型的数据private int toInt(byte[] byteData) {int intData = 0;for (int i = 0; i < byteData.length; i++) {int shift = (3 - i) * 8;intData += ((byteData[i] & 0xFF) << shift);}return intData;}}

2. server包

2.1 package-info.java

/*** 提供了一个简单的服务端,用以接收、回馈和转发客户端的消息* * @author JuJunjian* @version 1.0 -11-20*/package com.jujunjian.server;

2.2 UserSupervision.java

package com.jujunjian.server;import java.io.IOException;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import .Socket;import java.util.HashMap;import java.util.Map;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/*** 用于存储已注册用户的信息,同时提供向已注册用户发送消息、增加用户、删除用户以及其它一些辅助功能* * @author JuJunjian* @version 1.0 -11-20*/public class UserSupervision {private static final String CHARSET = "UTF-8"; // 传输数据的编码方式private static final int SEND_THREADS_NUMBER = 10;private static final int MAX_SIZE = 1000; // 最大聊天人数private static final Integer MIN_ID = 9000;private static final Integer MAX_ID = 9999;private Map<Integer, OutputStream> userOutputStreamMap;private Map<Integer, Socket> userSocketMap;private ExecutorService sendMessagePool;private int size; // 用于记录当前用户的数量/*** 实例化一个管理群聊用户的对象*/public UserSupervision() {userOutputStreamMap = new HashMap<>();userSocketMap = new HashMap<>();sendMessagePool = Executors.newFixedThreadPool(SEND_THREADS_NUMBER);size = 0;}/*** 检查注册账号是否满足格式要求* * @param id 需检测的账号* @return 账号符合要求返回true;否则返回false*/public boolean isRightId(Integer id) {if (id >= MIN_ID && id <= MAX_ID) {return true;}return false;}/*** 检测群聊人数是否已满* * @return 聊人数是否已满返回true;否则返回false*/public boolean isFull() {return (MAX_SIZE == size);}/*** 检测用户申请的账号是否已经被占用* * @param id 需检测的账号* @return 未被占用返回true;否则返回false*/public synchronized boolean isFreeId(Integer id) {if (userOutputStreamMap.containsKey(id)) {return false;}return true;}/*** 向群聊中添加新用户* * @param id 新注册用户的账号* @param socket 用于和此用户通讯的套接字* @param outputStream 用于向此用户发送消息的输出流* @return 添加成功返回true;否则返回false*/public synchronized boolean addUser(Integer id, Socket socket , OutputStream outputStream) {if (isFull()) {return false;} else {// 将此用户添加到群聊中userSocketMap.put(id, socket);userOutputStreamMap.put(id, outputStream);size++; // 当前群聊人数加一return true;}}/*** 从群聊中移除指定的用户* * @param deletedUserId 需被移除的用户的账号* @return 删除成功返回true;否则返回false*/public synchronized boolean removeUser(Integer deletedUserId) {if (userOutputStreamMap.isEmpty()) {return false;}if (userOutputStreamMap.containsKey(deletedUserId)) {try {// 关闭并移除此用户对应的OutputStream和SocketuserOutputStreamMap.get(deletedUserId).close();userOutputStreamMap.remove(deletedUserId);userSocketMap.get(deletedUserId).close();userSocketMap.remove(deletedUserId);size--; // 当前群聊人数减一return true;} catch (IOException e) {e.printStackTrace();}}return false;}/*** 向群内的其它用户(除了提供消息的用户)发送消息* * @param senderId 发送者的账号* @param message 发送的消息*/public synchronized void sendMessage(Integer senderId, String message) {for (Integer id : userOutputStreamMap.keySet()) {if(id != senderId) {sendMessagePool.submit(() -> {OutputStream out = userOutputStreamMap.get(id);// 将所需发送的消息转换为字节流,编码方式为UTF-8byte[] byteMessage = null;try {byteMessage = message.getBytes(CHARSET); } catch (UnsupportedEncodingException e) {e.printStackTrace();}// head是消息字节前面的报头,代表消息的长度,可辅助接收端判断是否接收完毕int length = byteMessage.length;byte[] head = toByte(length); // 得到最终需要传输的字节流outBytebyte[] outByte = new byte[length + head.length];System.arraycopy(head, 0, outByte, 0, head.length);System.arraycopy(byteMessage, 0, outByte, head.length, byteMessage.length);// 发送消息try {out.write(outByte);out.flush();} catch (IOException e) {e.printStackTrace();}});}}}/*** 获得空闲的账号* * @return 存在可用账号时返回一个可用账号,否则返回-1*/public synchronized Integer getFreeId() {Integer freeId = -1;if (isFull()) {return freeId;}// 遍历以寻找可用账号for (Integer id = MIN_ID; id < MAX_ID; id++) {if (!userOutputStreamMap.containsKey(id)) {freeId = id;break;}}return freeId;}/*** 调用此方法可结束群聊*/public synchronized void end() {userOutputStreamMap.clear();// 关闭所有socketfor (Integer id : userSocketMap.keySet()) {try {userSocketMap.get(id).close();} catch (IOException e) {e.printStackTrace();}}userSocketMap.clear();}/*** 将int类型的数据转换为4位byte类型的数据* * @param intData 传入的int类型的参数* @return 返回转换之后的4位byte类型的数据*/public static synchronized byte[] toByte(int intData) {byte[] byteData = new byte[4];byteData[0] = (byte) ((intData >> 24) & 0xFF);byteData[1] = (byte) ((intData >> 16) & 0xFF);byteData[2] = (byte) ((intData >> 8) & 0xFF);byteData[3] = (byte) (intData & 0xFF);return byteData;}/*** 将4位byte类型的数据转换为int类型的数据* * @param byteData 传入的4位byte类型的参数* @return 返回转换之后的int类型的数据*/public static synchronized int toInt(byte[] byteData) {int intData = 0;for (int i = 0; i < byteData.length; i++) {int shift = (3 - i) * 8;intData += ((byteData[i] & 0xFF) << shift);}return intData;}}

2.3 TerminalServer.java

package com.jujunjian.server;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import .ServerSocket;import .Socket;import .SocketException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/*** 实现了一个简单的群聊服务终端* * @author JuJunjian* @version 1.0 -11-20*/public class TerminalServer {private static final int TERMINAL_PORT = 8888; // 服务端的端口号private static final String CHARSET = "UTF-8"; // 传输数据的编码方式private UserSupervision userManager; // 群聊用户的管理者private ServerSocket terminalServerSocket;private ExecutorService receiveMessagePool;/*** 实例化一个服务终端对象*/public TerminalServer() {userManager = new UserSupervision();receiveMessagePool = Executors.newCachedThreadPool();try {terminalServerSocket = new ServerSocket(TERMINAL_PORT);} catch (IOException e) {e.printStackTrace();}}/*** 调用此方法可用使服务终端开始工作*/public void startRunning() {while (true) {try {Socket socket = terminalServerSocket.accept(); // 开始接收用户端建里连接的请求InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream();// 刚建立连接时会接收到4个字节的特殊消息,用于辅助服务端做出后续动作byte[] initialByte = new byte[4];inputStream.read(initialByte);int initialMessage = UserSupervision.toInt(initialByte);// 群聊结束,服务终端退出if (-1 == initialMessage) {userManager.end();}Integer uesrId = 0; // 用户申请的账号boolean isAvailableId = false; // 用于表示账号是否可用if (userManager.isFull()) {int result = 0; // 发送给客户端的数据,0 代表群聊已满byte[] byteResult = UserSupervision.toByte(result);outputStream.write(byteResult);outputStream.flush();} else {if (0 == initialMessage) {// initialMessage等于0表示用户正在申请一个随机的可用账号uesrId = userManager.getFreeId();int result = 3; // 3 代表未知的错误byte[] byteResult = new byte[4];if ((-1 != uesrId) && userManager.addUser(uesrId, socket, outputStream)) {isAvailableId = true;result = uesrId;}byteResult = UserSupervision.toByte(result);outputStream.write(byteResult);outputStream.flush();} else if (!userManager.isRightId(initialMessage)) {int result = 1; // 1 代表账号格式错误byte[] byteResult = UserSupervision.toByte(result);outputStream.write(byteResult);outputStream.flush();} else if (!userManager.isFreeId(initialMessage)) {int result = 2; // 2 代表账号已存在byte[] byteResult = UserSupervision.toByte(result);outputStream.write(byteResult);outputStream.flush();} else {uesrId = initialMessage;int result = 3; // 3 代表未知的错误byte[] byteResult = new byte[4];if (userManager.addUser(uesrId, socket, outputStream)) {isAvailableId = true; // 客户端申请的账号可用result = uesrId;}byteResult = UserSupervision.toByte(result);outputStream.write(byteResult);outputStream.flush();}}if (isAvailableId) {final Integer userFinalId = uesrId;receiveMessagePool.submit(() -> {// 建里连接之后就一直接收对方的消息,直至对方退出while (!socket.isClosed()) {try {// 前四位用于记录消息总长度,或断开通讯的通知(-1表示断开连接)byte[] byteHead = new byte[4];inputStream.read(byteHead);int head = UserSupervision.toInt(byteHead);// 结束与该用户的通讯if (-1 == head) {userManager.removeUser(userFinalId);inputStream.close();socket.close();break;} else {// 读取对方发送的消息byte[] messageByte = new byte[head];inputStream.read(messageByte);String message = new String(messageByte, CHARSET);userManager.sendMessage(userFinalId, message); // 将消息发送给其它用户}} catch (SocketException e) {System.out.println("一位用户已退出");} catch (IOException e) {e.printStackTrace();}}});}} catch (IOException e) {e.printStackTrace();}}}}

3. view包

3.1 package-info.java

/*** 提供客户端的界面,主要包括:聊天界面、登陆界面、警告弹窗、服务终端界面(用于结束服务终端程序)* * @author JuJunjian* @version 1.0 -11-21*/package com.jujunjian.view;

3.2 TerminalServerView.java

package com.jujunjian.view;import java.awt.Dimension;import java.awt.FlowLayout;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import javax.swing.JButton;import javax.swing.JFrame;import com.jujunjian.server.TerminalServer;/*** 服务终端界面,只包含一个结束按钮,用于结束终端服务器* * @author JuJunjian* @version 1.0 -11-21*/@SuppressWarnings("serial")public class TerminalServerView extends JFrame {private static final String TITLE = "服务终端";private static final String END_BUTTON_TEXT = "结束服务终端";private static final int FRAME_WIDTH = 300;private static final int FRAME_HIGH = 150;private static final int BUTTON_WIDTH = FRAME_WIDTH - 100;private static final int BUTTON_HIGH = FRAME_HIGH - 100;private JButton endButton;private TerminalServer terminalServer;private Thread terminalThread;/*** 实例化了一个服务终端界面*/public TerminalServerView() {// 开启服务终端terminalServer = new TerminalServer();terminalThread = new Thread(() -> {terminalServer.startRunning();});terminalThread.start();// 初始化界面setTitle(TITLE);setSize(FRAME_WIDTH, FRAME_HIGH);setResizable(false);setLayout(new FlowLayout(1, 30, 30));// 为右上角的叉号添加监听器和动作setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {terminalServer = null;System.exit(0);}});// 初始化结束按钮endButton = new JButton(END_BUTTON_TEXT);endButton.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HIGH));endButton.setFont(new java.awt.Font("宋体", 1, 20));endButton.addActionListener(e -> {terminalServer = null;System.exit(0);});add(endButton);setVisible(true);}public static void main(String[] args) {// 启动终端界面new TerminalServerView();}}

3.3 LoginView.java

package com.jujunjian.view;import java.awt.Dimension;import java.awt.FlowLayout;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JPanel;import javax.swing.JTextArea;import com.jujunjian.client.Client;/*** 用户登陆界面,大致包括:提示面板、账号输入面板、必须的按钮* * @author JuJunjian* @version 1.0 -11-21*/@SuppressWarnings("serial")public class LoginView extends JFrame {private static final Integer MIN_ID = 9000;private static final Integer MAX_ID = 9999;private static final String ERROR_TEXT = "账号有误";private static final String ID_EXIST_TEXT = "账号已存在";private static final String USER_FULL_TEXT = "群聊人数已满";private static final String UNKNOWN_ERROR_TEXT = "未知的错误";private static final String TITLE = "登陆界面";private static final String TIP_TEXT = "请输入账号(9000-9999):";private static final String OK_BUTTON_TEXT = "确定";private static final String GET_FREE_ID_TEXT = "获取随机账号";private static final int FRAME_WIDTH = 400;private static final int FRAME_HIGH = 240;private static final int TEXT_AREA_WIDTH = 350;private static final int TEXT_AREA_HIGH = 35;private static final int BUTTON_WIDTH = 170;private static final int BUTTON_HIGH = 50;private JTextArea inputIdTextArea;private JLabel errorTip;private JButton okButton;private JButton getFreeIdButton;/*** 实例化一个用户登陆界面*/public LoginView() {setTitle(TITLE);setSize(FRAME_WIDTH, FRAME_HIGH);setResizable(false);setLayout(new FlowLayout(1, 10, 10));setLocation(0, 150);// 为右上角的叉号添加监听器和动作setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {new WarningView();}});// 显示提示信息JLabel showTip = new JLabel(TIP_TEXT);showTip.setFont(new java.awt.Font("宋体", 1, 24));// 输入账号的面板inputIdTextArea = new JTextArea();inputIdTextArea.setPreferredSize(new Dimension(TEXT_AREA_WIDTH, TEXT_AREA_HIGH));inputIdTextArea.setFont(new java.awt.Font("宋体", 1, 24));// 输入账号有误时,给出的错误提示errorTip = new JLabel("");errorTip.setFont(new java.awt.Font("宋体", 1, 18));JPanel errorTipPanel = new JPanel(new FlowLayout());errorTipPanel.setPreferredSize(new Dimension(TEXT_AREA_WIDTH, TEXT_AREA_HIGH - 10));errorTipPanel.add(errorTip);// 初始化确认按钮okButton = new JButton(OK_BUTTON_TEXT);okButton.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HIGH));okButton.setFont(new java.awt.Font("宋体", 1, 20));okButton.addActionListener(e -> {final int uesrId = getInputId(); // 得到用户输入的账号if (-1 == uesrId) {// 账号中存在非数字errorTip.setText(ERROR_TEXT);} else {Client client = new Client(); // 每一个群聊用户都对应了一个客户端对象client.applyId(uesrId); // 向终端申请申请账号int result = client.getApplyIdResult(); // 得到申请账号的结果// 根据申请账号的结果进行处理switch (result) {case 0: // 群聊人数已满errorTip.setText(USER_FULL_TEXT);break;case 1: // 账号格式错误errorTip.setText(ERROR_TEXT);break;case 2: // 账号已存在errorTip.setText(ID_EXIST_TEXT);break;case 3: // 未知的错误errorTip.setText(UNKNOWN_ERROR_TEXT);break;default:if (uesrId == result) {// 申请成功inputIdTextArea.setText("");new ChatView(client, uesrId);} else {// 未知的错误errorTip.setText(UNKNOWN_ERROR_TEXT);}break;}}});// 初始化随机获得账号按钮getFreeIdButton = new JButton(GET_FREE_ID_TEXT);getFreeIdButton.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HIGH));getFreeIdButton.setFont(new java.awt.Font("宋体", 1, 20));getFreeIdButton.addActionListener(e -> {Client client = new Client();client.applyId(0); // 申请随机的账号int result = client.getApplyIdResult();if (0 == result) {// 0 代表群聊人数已满errorTip.setText(USER_FULL_TEXT);} else if ((result >= MIN_ID) && (result <= MAX_ID)) {// 申请成功inputIdTextArea.setText("");new ChatView(client, result);} else {errorTip.setText("未知的错误");}});add(showTip);add(inputIdTextArea);add(errorTipPanel);add(okButton);add(getFreeIdButton);setVisible(true);}// 得到用户输入的Id,读取失败时返回-1private Integer getInputId() {Integer inputId = -1;String stringId = inputIdTextArea.getText();try {inputId = Integer.valueOf(stringId);} catch (Exception e) {}return inputId;}public static void main(String[] args) {new LoginView();}}

3.4 ChatView.java

package com.jujunjian.view;import java.awt.BorderLayout;import java.awt.Dimension;import java.awt.FlowLayout;import java.awt.Font;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.JScrollPane;import javax.swing.JTextArea;import com.jujunjian.client.Client;/*** 用户群聊天界面,大致包括:消息显示面板、输入面板、发送按钮* * @author JuJunjian* @version 1.0 -11-21*/@SuppressWarnings("serial")public class ChatView extends JFrame {private static final String TITLE = "用户:";private static final String SEND_BUTTON_TEXT = "发送";private static final int FRAME_WIDTH = 1100;private static final int FRAME_HIGH = 900;private static final int PANEL_WIDTH = FRAME_WIDTH - 50;private static final int CHAT_PANEL_HIGH = 500;private static final int INPUT_PANEL_HIGH = 250;private static final int SEND_BUTTON_WIDTH = 200;private static final int SEND_BUTTON_HIGH = 60;private JPanel chatPanel;private JPanel inputPanel;private JTextArea chatArea;private JTextArea inputArea;private JButton sendButton;private Integer id; // 用户账号private Client client; // 用户对应的客户端对象private Thread receiveThread;private Thread sendThread;private boolean isRunning; // 用户的状态(false表示用户已退出群聊)/*** 实例化一个群聊界面* * @param client 注册界面申请成功之后得到的客户端对象* @param id 用户的账号*/public ChatView(Client client, int id) {// 初始客户端this.client = client;this.id = id;isRunning = true;// 界面初始化setTitle(TITLE + this.id);setSize(FRAME_WIDTH, FRAME_HIGH);setResizable(false);setLocationRelativeTo(null); // 窗口居中setLayout(new FlowLayout(2, 10, 10));// 为右上角的叉号添加监听器和动作setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {// 用户退出isRunning = false;client.endCommunication(); // 结束通讯dispose();}});// 消息显示面板chatArea = new JTextArea();initialJTextArea(chatArea);chatPanel = new JPanel();initialJPanel(chatPanel, PANEL_WIDTH, CHAT_PANEL_HIGH);chatPanel.add(new JScrollPane(chatArea));// 消息发送面板inputArea = new JTextArea();initialJTextArea(inputArea);inputPanel = new JPanel();initialJPanel(inputPanel, PANEL_WIDTH, INPUT_PANEL_HIGH);inputPanel.add(new JScrollPane(inputArea), BorderLayout.CENTER);// 发送按钮sendButton = new JButton(SEND_BUTTON_TEXT);sendButton.setPreferredSize(new Dimension(SEND_BUTTON_WIDTH, SEND_BUTTON_HIGH));sendButton.setFont(new Font("宋体", 1, 24));sendButton.addActionListener(e -> {sendMessage("用户" + id + ":\n" + inputArea.getText() + "\n\n");chatArea.append("我:\n" + inputArea.getText() + "\n\n");inputArea.setText("");});startReceive(); // 开始接收消息add(chatPanel);add(inputPanel);add(sendButton);setVisible(true);}// 调用此方法发送一次消息private void sendMessage(String message) {sendThread = new Thread(() -> {client.sendMessage(message);});sendThread.start();}// 调用此方法开始接收消息private void startReceive() {receiveThread = new Thread(() -> {while (isRunning) {String message = client.startReceiveMessage();chatArea.append(message);}});receiveThread.start();}// 设置JTextArea的字体private void initialJTextArea(JTextArea textArea) {textArea.setFont(new Font("宋体", 0, 24));}// 设置JPanel的大小和排版private void initialJPanel(JPanel panel, int width, int high) {panel.setPreferredSize(new Dimension(width, high));panel.setLayout(new BorderLayout());}}

3.5 WarningView.java

package com.jujunjian.view;import java.awt.Dimension;import java.awt.FlowLayout;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JPanel;import com.jujunjian.client.Client;/*** 警告弹窗,关闭登陆界面时弹出,提示用户关闭此界面将结束整个群聊程序* * @author JuJunjian* @version 1.0 -11-21*/@SuppressWarnings("serial")public class WarningView extends JFrame {private static final String WARNING_TEXT = "关闭此窗口将结束整个群聊程序,是否关闭?";private static final String OK_BUTTON_TEXT = "确定";private static final String CANCEL_BUTTON_TEXT = "取消";private static final int FRAME_WIDTH = 600;private static final int FRAME_HIGH = 200;private static final int TEXT_LABEL_WIDTH = 600;private static final int TEXT_LABEL_HIGH = 50;private static final int BUTTON_WIDTH = 170;private static final int BUTTON_HIGH = 50;private static final int END_ID = -1; // 结束群聊private JLabel warningLabel;private JButton okButton;private JButton cancelButton;private Thread endThread;/*** 实例化一个警告窗口,尝试结束群聊(关闭登陆界面)时会弹出*/public WarningView() {setSize(FRAME_WIDTH, FRAME_HIGH);setResizable(false);setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // 只关闭当前窗口setLocationRelativeTo(null);setLayout(new FlowLayout(1, 20, 20));// 显示提示信息warningLabel = new JLabel(WARNING_TEXT);warningLabel.setFont(new java.awt.Font("宋体", 1, 24));JPanel warningPanel = new JPanel(new FlowLayout());warningPanel.setPreferredSize(new Dimension(TEXT_LABEL_WIDTH, TEXT_LABEL_HIGH));warningPanel.add(warningLabel);// 初始化确认按钮okButton = new JButton(OK_BUTTON_TEXT);okButton.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HIGH));okButton.setFont(new java.awt.Font("宋体", 1, 20));okButton.addActionListener(e -> {endThread = new Thread(() -> {Client client = new Client();client.applyId(END_ID); // 告诉服务终端群聊已结束});endThread.start();System.exit(0);});// 初始化取消按钮cancelButton = new JButton(CANCEL_BUTTON_TEXT);cancelButton.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HIGH));cancelButton.setFont(new java.awt.Font("宋体", 1, 20));cancelButton.addActionListener(e -> {dispose();});add(warningPanel);add(okButton);add(cancelButton);setVisible(true);}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。