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

聊天的表情包+发小文件+图片操作

其实我的文件也就是通过和图片差不多的实现思路,基本上一样

表情包实现(unicode字符串自带的表情包)

你的代码实现了一个聊天应用中的表情包选择、图片发送和小文件发送功能。以下是对你实现思路的详细讲解:

1. 表情包功能

功能描述

用户点击某个按钮后,弹出一个表情选择面板,用户可以选择表情符号并将其插入到聊天输入框中。

实现思路
  • 创建表情面板
    • 使用 Stage 创建一个独立的弹窗窗口 emojiStage,用于显示表情选择面板。
    • 使用 GridPane 布局来排列表情按钮,设置内边距、水平间距和垂直间距,使表情按钮整齐排列。
  • 定义表情数据
    • 使用一个字符串数组 emojis 存储常用的表情符号,每个表情符号是一个 Unicode 字符串。
  • 生成表情按钮
    • 遍历 emojis 数组,为每个表情符号创建一个 Button
    • 设置按钮的字体为支持表情符号的字体(如 Segoe UI Emoji),并设置字体大小为 20。
    • 为每个按钮添加点击事件处理器,当按钮被点击时,调用 insertEmoji 方法,将对应的表情符号插入到聊天输入框中。
    • 使用 GridPaneadd 方法将按钮添加到网格布局中,通过 i % 5i / 5 计算按钮在网格中的行列位置,实现每行显示 5 个表情按钮。
  • 显示表情面板
    • 创建一个 Scene,将 GridPane 设置为场景的根节点。
    • 将场景设置到 emojiStage,并调用 show 方法显示表情面板。
优点
  • 界面简洁,用户可以快速选择常用表情。
  • 使用 GridPane 布局,表情按钮排列整齐,易于扩展。
    private void showEmojiPanel(ActionEvent event) {// 创建简单表情选择弹窗Stage emojiStage = new Stage();GridPane emojiGrid = new GridPane();emojiGrid.setPadding(new Insets(10));emojiGrid.setHgap(5);emojiGrid.setVgap(5);// 定义一组常用表情String[] emojis = {"\uD83D\uDE00", // 😀"\uD83D\uDE02", // 😂"\u2764\uFE0F", // ❤️"\uD83D\uDE80", // 🚀"\uD83C\uDF89", // 🎉\"\uD83D\uDE1A","\uD83D\uDE19","\uD83E\uDD72","\uD83E\uDD10","\uD83E\uDD28","\uD83D\uDE10","\uD83D\uDE11","\uD83D\uDE36","\uD83E\uDEE5"};// 添加表情按钮for (int i = 0; i < emojis.length; i++) {Button emojiButton = new Button(emojis[i]);emojiButton.setFont(Font.font("Segoe UI Emoji", 20));int finalI = i;emojiButton.setOnAction(e -> insertEmoji(emojis[finalI]));emojiGrid.add(emojiButton, i % 5, i / 5);}Scene scene = new Scene(emojiGrid);emojiStage.setScene(scene);emojiStage.show();}

2. 图片发送功能

功能描述

用户通过文件选择器选择一张图片,应用对图片进行大小限制(不超过 5MB),然后将图片发送到服务器,并在本地保存一份副本。

实现思路
  • 选择图片
    • 使用 FileChooser 创建一个文件选择器,设置标题为“选择要发送的图片”。
    • 添加文件扩展名过滤器,限制用户只能选择 .png.jpg.jpeg 格式的图片文件。
    • 调用 showOpenDialog 方法弹出文件选择对话框,获取用户选择的文件。
  • 验证文件大小
    • 获取文件的大小(selectedFile.length()),判断是否超过 5MB。如果超过,调用 showAlert 方法提示用户“图片大小不能超过5MB”,并返回。
  • 处理图片并发送
    • 在一个新线程中执行图片处理和发送操作,避免阻塞主线程。
    • 使用 FileTransferUtil.fileToByte 方法将图片文件转换为字节数组。
    • 构造一个 FileTransferUtil.FileTransferWrapper 对象,包含文件名、字节数组、状态码(4 表示聊天图片)和用户 ID。
    • 保存本地副本:
      • 定义本地保存路径 clientPath
      • 使用 FileInputStream 读取图片文件,通过 FileOutputStream 将图片内容写入到本地路径。
      • 如果目标目录不存在,尝试创建目录。
    • 构造 ChatMessage 对象,包含文件路径、消息类型(4 表示图片)、发送者信息、聊天室 ID、是否为好友群聊以及发送者头像路径。
    • 构造 Even 对象,包含文件传输包装器和操作码(36 表示图片发送操作)。
    • 调用 SocketLongTUtil.sendRequest4 方法将图片消息发送到服务器。
    • 更新本地消息列表:
      • 使用 Platform.runLater 确保在 JavaFX 的主线程中更新界面。
      • serverMessage 添加到消息列表中,并刷新 messageListView
  • 错误处理
    • 如果在图片处理或发送过程中发生异常,捕获异常并通过 showAlert 方法提示用户“图片发送失败: [异常信息]”。
优点
  • 对图片大小进行了限制,避免发送过大的图片导致性能问题。
  • 在后台线程中处理图片发送,不会阻塞主线程,用户体验更好。
  • 发送成功后,本地保存一份副本,方便后续查看。
    void sendImage(ActionEvent event) {FileChooser fileChooser = new FileChooser();fileChooser.setTitle("选择要发送的图片");fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("图片文件", "*.png", "*.jpg", "*.jpeg"));File selectedFile = fileChooser.showOpenDialog(messageInput.getScene().getWindow());if (selectedFile != null) {// 验证文件大小(示例限制5MB)if (selectedFile.length() > 5 * 1024 * 1024) {showAlert("图片大小不能超过5MB");return;}new Thread(() -> {try {// 3. 转换为字节数组并发送byte[] fileData = FileTransferUtil.fileToByte(selectedFile);// 构造文件传输包装器FileTransferUtil.FileTransferWrapper wrapper = new FileTransferUtil.FileTransferWrapper(selectedFile.getName(),fileData,4,  // 使用状态码4表示聊天图片MainController.user.getId());MainController.selectedFile=selectedFile;//发送完就保存String clientPath="D:/develop/code/demo6/src/main/resources/upload/";try(FileInputStream fis=new FileInputStream(selectedFile)){//创建目标目录(如果不存在)if(!selectedFile.exists()&&!selectedFile.mkdirs()){throw new Exception("无法创建目录"+selectedFile);}//生成文件名clientPath= clientPath+selectedFile.getName();try(FileOutputStream fos=new FileOutputStream(clientPath)){byte[] buffer=new byte[1024];int len;while((len=fis.read(buffer))!=-1){fos.write(buffer,0,len);}}} catch (FileNotFoundException e) {throw new RuntimeException(e);} catch (Exception e) {throw new RuntimeException(e);}ChatMessage serverMessage = new ChatMessage(clientPath,4,user,currentRoomId,isFriendGroup,user.getAvatarPath());// 发送消息(使用操作码4)Even even = new Even(wrapper, 36);even.setObjectFriend(serverMessage);even.setUserId(MainController.user.getId());even.setIsFriend(isFriendGroup);SocketLongTUtil.sendRequest4(even);serverMessage.setFromMe(true);Platform.runLater(() -> {updateMessageList(serverMessage);messageListView.refresh();});} catch (Exception e) {Platform.runLater(() ->showAlert("图片发送失败: " + e.getMessage()));}}).start();}}

3. 小文件发送功能

功能描述

用户通过文件选择器选择一个小文件(不超过 20MB),应用将文件发送到服务器,并在本地保存一份副本。

实现思路
  • 选择文件
    • 使用 FileChooser 创建一个文件选择器,设置标题为“选择要发送的文件”。
    • 调用 showOpenDialog 方法弹出文件选择对话框,获取用户选择的文件。
  • 验证文件大小
    • 获取文件的大小(selectedFile.length()),判断是否超过 20MB。如果超过,调用 showAlert 方法提示用户“文件大小不能超过20MB”,并返回。
  • 处理文件并发送
    • 在一个新线程中执行文件处理和发送操作,避免阻塞主线程。
    • 使用 Files.readAllBytes 方法将文件内容读取为字节数组。
    • 定义本地保存路径 clientPath,路径中包含随机生成的 UUID 和文件名,避免文件名冲突。
    • 使用 Files.copy 方法将文件从原始路径复制到本地保存路径。
    • 构造 ChatMessage 对象,包含文件路径、消息类型(5 表示文件)、发送者信息、聊天室 ID、是否为好友群聊以及发送者头像路径。
    • 构造 Even 对象,包含文件传输包装器和操作码(37 表示文件发送操作)。
    • 调用 SocketLongTUtil.sendRequest4 方法将文件消息发送到服务器。
    • 更新本地消息列表:
      • 使用 Platform.runLater 确保在 JavaFX 的主线程中更新界面。
      • fileMessage 添加到消息列表中,并刷新 messageListView
  • 错误处理
    • 如果在文件处理或发送过程中发生异常,捕获异常并通过 showAlert 方法提示用户“文件发送失败: [异常信息]”。
    void sendFile(ActionEvent event) {FileChooser fileChooser = new FileChooser();fileChooser.setTitle("选择要发送的文件");File selectedFile = fileChooser.showOpenDialog(messageInput.getScene().getWindow());if (selectedFile != null) {// 限制文件大小(例如20MB)if (selectedFile.length() > 20 * 1024 * 1024) {showAlert("文件大小不能超过20MB");return;}new Thread(() -> {try {// 读取文件并构建消息byte[] fileData = Files.readAllBytes(selectedFile.toPath());String clientPath = "D:/develop/code/demo6/src/main/resources/upload/"+ UUID.randomUUID() + "_" + selectedFile.getName();// 保存本地副本Files.copy(selectedFile.toPath(), Paths.get(clientPath));// 构建消息对象ChatMessage fileMessage = new ChatMessage(clientPath,5, // 文件类型标识user,currentRoomId,isFriendGroup,user.getAvatarPath());fileMessage.setFileName(selectedFile.getName());// 发送到服务器Even even = new Even(new FileTransferUtil.FileTransferWrapper(selectedFile.getName(),fileData,5, // 文件类型user.getId()),37 // 文件传输操作码);even.setUserId(MainController.user.getId());even.setIsFriend(isFriendGroup);even.setObjectFriend(fileMessage);SocketLongTUtil.sendRequest4(even);// 更新本地界面fileMessage.setFromMe(true);Platform.runLater(() -> {updateMessageList(fileMessage);
//                        messageListView.scrollTo(messageListView.getItems().size() - 1);messageListView.refresh();});} catch (Exception e) {Platform.runLater(() ->showAlert("文件发送失败: " + e.getMessage()));}}).start();}}

相关文章:

  • 《P5283 [十二省联考 2019] 异或粽子》
  • Hugo 安装保姆级教程(搭建个人blog)
  • 软件架构设计--期末复习
  • HiTool机顶盒刷机提示:网络下载TFTP超时,可能的原因如下
  • volatile
  • DeepSeek 赋能太空探索:从轨道优化到星际开拓的 AI 革命
  • DAY 29 复习日:类的装饰器
  • tauri2项目动态添加 Sidecar可行性方案(运行时配置)
  • 高能数造闪耀 CIBF 2025,以创新技术引领新能源智造新征程
  • 基于MCP的AI Agent应用开发实践
  • 【ComfyUI】关于ComfyUI的一些基础知识和入门设置以及快捷键小技巧【简单易懂】
  • 通过串口设备的VID PID动态获取串口号(C# C++)
  • Java基于数组的阻塞队列实现详解
  • 算法-js-柱状图中最大的矩形
  • Qt如何设置图标
  • 【PyQt5实战】五大对话框控件详解:从文件选择到消息弹窗
  • 等于和绝对等于的区别
  • CHAIN-OF-TABLE: 推理链中的演化表格用于表格理解
  • 智慧园区数据大脑管理平台整体解决方案
  • USB学习【11】STM32 USB初始化过程详解
  • 中美博弈新阶段,这个“热带中国”火了
  • 上博东馆常设陈列入选全国博物馆“十大精品”
  • 被围观的“英之园”,谁建了潮汕天价违建?
  • 受关税政策影响,沃尔玛将上调部分商品在美售价
  • 新任美国驻华大使庞德伟抵京履职,外交部回应
  • 中欧金融工作组第二次会议在比利时布鲁塞尔举行