当前位置: 首页 > news >正文

【VSCode】VSCode为Java C/S项目添加图形用户界面

为Java C/S项目添加图形用户界面

现在我们来为它添加图形用户界面(GUI)。我将使用Java Swing库创建一个简单的GUI,因为它内置于Java标准库中,无需额外依赖。

客户端GUI实现

首先,我们将修改客户端代码,添加一个Swing GUI界面:

修改后的Client.java(带GUI)

import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;public class Client {private static final String SERVER_ADDRESS = "localhost";private static final int SERVER_PORT = 12345;// GUI组件private JFrame frame;private JTextField messageField;private JTextArea chatArea;private JButton sendButton;private JTextField nameField;private JButton connectButton;// 网络连接private Socket socket;private ObjectOutputStream out;private ObjectInputStream in;private String clientName;private boolean connected = false;public static void main(String[] args) {SwingUtilities.invokeLater(() -> {try {new Client().createAndShowGUI();} catch (Exception e) {e.printStackTrace();}});}private void createAndShowGUI() {// 创建主窗口frame = new JFrame("聊天客户端");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setSize(500, 400);frame.setLayout(new BorderLayout());// 顶部面板 - 连接信息JPanel topPanel = new JPanel(new FlowLayout());topPanel.add(new JLabel("用户名:"));nameField = new JTextField("用户", 10);topPanel.add(nameField);connectButton = new JButton("连接服务器");connectButton.addActionListener(e -> connectToServer());topPanel.add(connectButton);frame.add(topPanel, BorderLayout.NORTH);// 中间面板 - 聊天内容chatArea = new JTextArea();chatArea.setEditable(false);JScrollPane scrollPane = new JScrollPane(chatArea);frame.add(scrollPane, BorderLayout.CENTER);// 底部面板 - 消息输入JPanel bottomPanel = new JPanel(new BorderLayout());messageField = new JTextField();messageField.addActionListener(e -> sendMessage());sendButton = new JButton("发送");sendButton.addActionListener(e -> sendMessage());bottomPanel.add(messageField, BorderLayout.CENTER);bottomPanel.add(sendButton, BorderLayout.EAST);frame.add(bottomPanel, BorderLayout.SOUTH);// 设置窗口可见frame.setVisible(true);}private void connectToServer() {if (connected) {appendToChat("已经连接到服务器");return;}clientName = nameField.getText().trim();if (clientName.isEmpty()) {JOptionPane.showMessageDialog(frame, "请输入用户名", "错误", JOptionPane.ERROR_MESSAGE);return;}// 在新线程中连接服务器,避免阻塞UInew Thread(() -> {try {socket = new Socket(SERVER_ADDRESS, SERVER_PORT);out = new ObjectOutputStream(socket.getOutputStream());in = new ObjectInputStream(socket.getInputStream());connected = true;SwingUtilities.invokeLater(() -> {connectButton.setText("断开连接");appendToChat("已连接到服务器");});// 启动接收消息的线程new Thread(this::receiveMessages).start();} catch (IOException e) {SwingUtilities.invokeLater(() -> {JOptionPane.showMessageDialog(frame, "无法连接到服务器: " + e.getMessage(), "连接错误", JOptionPane.ERROR_MESSAGE);});}}).start();}private void disconnect() {connected = false;try {if (out != null) out.close();if (in != null) in.close();if (socket != null) socket.close();} catch (IOException e) {e.printStackTrace();}SwingUtilities.invokeLater(() -> {connectButton.setText("连接服务器");appendToChat("已断开与服务器的连接");});}private void sendMessage() {if (!connected) {JOptionPane.showMessageDialog(frame, "请先连接到服务器", "错误", JOptionPane.ERROR_MESSAGE);return;}String messageText = messageField.getText().trim();if (messageText.isEmpty()) {return;}try {Message message = new Message(clientName, messageText);out.writeObject(message);out.flush();messageField.setText("");} catch (IOException e) {appendToChat("发送消息失败: " + e.getMessage());disconnect();}}private void receiveMessages() {try {Message message;while (connected && (message = (Message) in.readObject()) != null) {final Message finalMessage = message;SwingUtilities.invokeLater(() -> appendToChat(finalMessage.toString()));}} catch (IOException | ClassNotFoundException e) {if (connected) { // 只在仍然连接时显示错误SwingUtilities.invokeLater(() -> {appendToChat("与服务器的连接已断开");disconnect();});}}}private void appendToChat(String text) {chatArea.append(text + "\n");chatArea.setCaretPosition(chatArea.getDocument().getLength());}
}

服务器管理界面

虽然服务器通常不需要GUI,但为了方便监控,我们可以添加一个简单的管理界面:

修改后的Server.java(带管理界面)

import java.io.*;
import java.net.*;
import java.util.concurrent.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;public class Server {private static final int PORT = 12345;private static ExecutorService pool = Executors.newFixedThreadPool(10);private static ServerSocket serverSocket;private static boolean running = false;private static List<ClientHandler> clients = new ArrayList<>();// GUI组件private JFrame frame;private JTextArea logArea;private JButton startButton;private JButton stopButton;public static void main(String[] args) {SwingUtilities.invokeLater(() -> {try {new Server().createAndShowGUI();} catch (Exception e) {e.printStackTrace();}});}private void createAndShowGUI() {// 创建主窗口frame = new JFrame("聊天服务器");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setSize(600, 400);frame.setLayout(new BorderLayout());// 顶部面板 - 控制按钮JPanel topPanel = new JPanel(new FlowLayout());startButton = new JButton("启动服务器");startButton.addActionListener(e -> startServer());topPanel.add(startButton);stopButton = new JButton("停止服务器");stopButton.addActionListener(e -> stopServer());stopButton.setEnabled(false);topPanel.add(stopButton);frame.add(topPanel, BorderLayout.NORTH);// 中间面板 - 日志logArea = new JTextArea();logArea.setEditable(false);JScrollPane scrollPane = new JScrollPane(logArea);frame.add(scrollPane, BorderLayout.CENTER);// 底部面板 - 状态信息JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));bottomPanel.add(new JLabel("客户端数量: 0"));frame.add(bottomPanel, BorderLayout.SOUTH);// 设置窗口可见frame.setVisible(true);}private void startServer() {if (running) {appendLog("服务器已经在运行中");return;}new Thread(() -> {try {serverSocket = new ServerSocket(PORT);running = true;SwingUtilities.invokeLater(() -> {startButton.setEnabled(false);stopButton.setEnabled(true);appendLog("服务器已启动,监听端口: " + PORT);});while (running) {try {Socket clientSocket = serverSocket.accept();appendLog("新客户端连接: " + clientSocket.getInetAddress());ClientHandler clientThread = new ClientHandler(clientSocket);clients.add(clientThread);pool.execute(clientThread);} catch (IOException e) {if (running) { // 只有在服务器仍在运行时才记录错误appendLog("接受客户端连接时出错: " + e.getMessage());}}}} catch (IOException e) {appendLog("启动服务器失败: " + e.getMessage());}}).start();}private void stopServer() {running = false;try {if (serverSocket != null && !serverSocket.isClosed()) {serverSocket.close();}} catch (IOException e) {appendLog("关闭服务器时出错: " + e.getMessage());}// 断开所有客户端连接for (ClientHandler client : clients) {client.disconnect();}clients.clear();startButton.setEnabled(true);stopButton.setEnabled(false);appendLog("服务器已停止");}private void appendLog(String text) {SwingUtilities.invokeLater(() -> {logArea.append(new Date() + " - " + text + "\n");logArea.setCaretPosition(logArea.getDocument().getLength());});}private class ClientHandler implements Runnable {private Socket clientSocket;private ObjectOutputStream out;private ObjectInputStream in;private String clientName;public ClientHandler(Socket socket) {this.clientSocket = socket;}@Overridepublic void run() {try {out = new ObjectOutputStream(clientSocket.getOutputStream());in = new ObjectInputStream(clientSocket.getInputStream());Message message;while (running && (message = (Message) in.readObject()) != null) {clientName = message.getSender(); // 记录客户端名称appendLog("收到来自 " + clientName + " 的消息: " + message.getContent());// 广播给所有客户端broadcastMessage(message);}} catch (IOException | ClassNotFoundException e) {appendLog("客户端 " + (clientName != null ? clientName : clientSocket.getInetAddress()) + " 断开连接");} finally {disconnect();clients.remove(this);}}public void disconnect() {try {if (in != null) in.close();if (out != null) out.close();if (clientSocket != null) clientSocket.close();} catch (IOException e) {// 忽略关闭时的异常}}private void broadcastMessage(Message message) {for (ClientHandler client : clients) {try {client.out.writeObject(message);client.out.flush();} catch (IOException e) {appendLog("向客户端发送消息失败: " + e.getMessage());client.disconnect();clients.remove(client);}}}}
}

编译和运行

  1. 重新编译所有文件:

    javac -encoding UTF-8 -d shared/bin shared/src/Message.java
    javac -encoding UTF-8 -cp "shared/bin" -d server/bin server/src/Server.java
    javac -encoding UTF-8 -cp "shared/bin" -d client/bin client/src/Client.java
    
  2. 先运行服务器:

    java -cp "server/bin;shared/bin" Server
    
  3. 然后运行一个或多个客户端:

    java -cp "client/bin;shared/bin" Client
    

界面功能说明

客户端界面功能:

  1. 输入用户名
  2. 连接/断开服务器按钮
  3. 消息输入框和发送按钮
  4. 聊天内容显示区域

服务器界面功能:

  1. 启动/停止服务器按钮
  2. 服务器日志显示区域
  3. 显示客户端连接状态

扩展建议

  1. 美化界面:使用更现代的界面风格,可以考虑使用JavaFX而不是Swing
  2. 添加更多功能
    • 用户列表显示
    • 私聊功能
    • 文件传输
    • 表情符号支持
  3. 持久化存储:将聊天记录保存到数据库
  4. 用户认证:添加登录/注册功能
  5. 群组聊天:支持创建和加入不同的聊天室

这个GUI版本应该能让您的C/S项目更加用户友好,同时保留了原有的所有功能。

http://www.dtcms.com/a/353780.html

相关文章:

  • YOLOv8-SMOT:一种高效鲁棒的实时小目标跟踪框架:基于切片辅助训练与自适应关联
  • 腾讯云 CVM 上的 SpringBoot 应用避免非法访问
  • Redis实战-优惠券秒杀解决方案总结大全
  • 开疆智能Profinet转EtherCAT网关连接TR-Electronic传感器配置案例
  • 部署网页在服务器(公网)上笔记 infinityfree 写一个找工作单html文件的网站
  • 分享 HTML 邮件开发的 15 个踩坑实录
  • Ubuntu 切换 SOCKS5代理 和 HTTP 代理并下载 Hugging Face 模型
  • 树莓派装的Ubuntu Server连接不上WIFI
  • Day14——JavaScript 核心知识全解析:变量、类型与操作符深度探秘
  • DeFi协议Lombard能突破比特币生态原生叙事困境吗?
  • 鸿蒙ArkUI 基础篇-06-组件基础语法-Column/Row/Text
  • 主键索引和普通索引的区别
  • 移动端(微信等)使用 vConsole调试console
  • 吱吱企业通讯软件打破跨部门沟通壁垒,为企业搭建安全的通讯环境
  • 论文Review 3DGS PGSR | TVCG2024 ZJU-3DV | 几何约束的3DGS表面重建
  • 京东大模型安全实践:从全链路防护到合规备案的完整技术方案
  • Apache Flink错误处理实战手册:2年生产环境调试经验总结
  • 私域电商新范式:开源AI智能名片链动2+1模式S2B2C商城小程序赋能传统行业流量转化
  • 从感知机到大模型:神经网络的全景解析与实践指南
  • MQTT broker 安装与基础配置实战指南(二)
  • STM32——中断
  • PLC_博图系列☞基本指令”PT:加载持续时间“
  • 基于Kafka的延迟队列
  • 身份证号校验码算法
  • C++中类继承的意义
  • PMP项目管理知识点-⑮预测型项目概念辨析
  • 【Kafka】项目整合使用案例
  • 瑞芯微开发工具Linux Linux_Upgrade_Tool使用方法(镜像烧录)
  • Python 比较huggingface_hub库的hf_hub_download函数和snapshot_download函数
  • 在 .NET 8.0 中实现 JWT 刷新令牌