Javafx模拟QQ机制实现发送表情包的功能

首先,我们来看看QQ发送表情包的方法(发表情包不简单吗?不就是点击一下?)

当我们在待输入框里输入   " / "   的时候,我们发送有提示信息。

Javafx模拟QQ机制实现发送表情包的功能

 

 

结果发现,当我们输入 "/xk"的时候,会直接定位到笑哭的这个表情。

   因此我的想法是,当我输入  "//" 含有两个反斜杠的文本消息时,线程那边将会判断它是一个表情包。然后通过"//00","//01","//02"这类字符串,去提取字符串后两位的字符,然后去本地路径去调用图片表情包。因此:"00" , "01" , "02" 就要成为图片的名字。否则匹配不方便。

图片名和路径如下:

Javafx模拟QQ机制实现发送表情包的功能

 

 

 

线程判断和匹配如下:

Stage牛逼,模拟一切弹窗(主要是我太菜了)。

 1 if(str.contains("//")){
 2     Platform.runLater(new Runnable(){
 3         public void run(){
 4             Stage stage = new Stage();
 5             BorderPane bp = new BorderPane();
 6             String[]  strs=str.split("//");
 7             String img_name = strs[1];
 8             Image image = new Image("file:表情包/"+img_name+".jpg");
 9             ImageView iv = new ImageView(image);
10             bp.setCenter(iv);
11             Scene scene = new Scene(bp);
12             stage.setTitle("表情");
13             stage.setScene(scene);
14             stage.centerOnScreen();
15             stage.show();
16         }
17     });    
18 }

完整代码如下:

  1 package 测试;
  2 
  3 import java.io.File;
  4 import java.io.FileInputStream;
  5 import java.io.FileOutputStream;
  6 import java.io.IOException;
  7 import java.io.InputStream;
  8 import java.io.OutputStream;
  9 import java.net.DatagramPacket;
 10 import java.net.InetAddress;
 11 import java.net.MulticastSocket;
 12 import java.text.SimpleDateFormat;
 13 import java.util.Date;
 14 import java.util.Optional;
 15 
 16 import javafx.application.Application;
 17 import javafx.application.Platform;
 18 import javafx.event.ActionEvent;
 19 import javafx.scene.Scene;
 20 import javafx.scene.control.Alert;
 21 import javafx.scene.control.Button;
 22 import javafx.scene.control.ButtonType;
 23 import javafx.scene.control.Label;
 24 import javafx.scene.control.ScrollPane;
 25 import javafx.scene.control.TextArea;
 26 import javafx.scene.control.TextField;
 27 import javafx.scene.control.TitledPane;
 28 import javafx.scene.image.Image;
 29 import javafx.scene.image.ImageView;
 30 import javafx.scene.layout.AnchorPane;
 31 import javafx.scene.layout.BorderPane;
 32 import javafx.scene.layout.VBox;
 33 import javafx.scene.text.Font;
 34 import javafx.stage.FileChooser;
 35 import javafx.stage.Stage;
 36 import sun.misc.BASE64Decoder;
 37 import sun.misc.BASE64Encoder;
 38 
 39 public class FX_UDP extends Application {
 40     static InetAddress ia;
 41     static MulticastSocket socket, socket2, socket1;// socket(6760)
 42                                                     // 聊天,socket1(6770)
 43                                                     // 窗口颤抖,socket2(6880) 图片流
 44     static TextArea ta_1, ta_2;
 45     static TextField tf_name;
 46     static Stage s1;
 47 
 48     public static void main(String[] args) {
 49         try {
 50             ia = InetAddress.getByName("228.9.6.7");
 51             socket = new MulticastSocket(6760);
 52             socket.joinGroup(ia);
 53             new Private_recive().start();
 54             new Image_recive().start();
 55         } catch (IOException e1) {
 56             System.out.println("组播地址绑定失败");
 57         }
 58         Application.launch();
 59     }
 60 
 61     @Override
 62     public void start(Stage s) throws Exception {
 63         s1 = s;
 64         Label lb_net = new Label("网名:");
 65         lb_net.setFont(Font.font(17));// 设置字体大小
 66         tf_name = new TextField("JDR");
 67 
 68         /* 消息记录 */
 69         ta_1 = new TextArea();
 70         ta_1.setPrefSize(400, 200);
 71         ScrollPane pane_info = new ScrollPane(ta_1);
 72         TitledPane pane_01 = new TitledPane("消息记录", pane_info);
 73         /* 发送窗口 */
 74         ta_2 = new TextArea();
 75         ta_2.setPrefSize(400, 100);
 76         ScrollPane pane_send = new ScrollPane(ta_2);
 77         TitledPane pane_02 = new TitledPane("发送窗口", pane_send);
 78         /* 发送和按钮事件 */
 79         Button btn_send = new Button("发送");
 80         btn_send.setOnAction(this::btnSend);
 81         /* 关闭和按钮事件 */
 82         Button btn_close = new Button("关闭");
 83         btn_close.setOnAction(this::btnClose);
 84         /* 发送图片和按钮事件 */
 85         Button btn_img = new Button("选择图片");
 86         btn_img.setOnAction(this::btnImg);
 87         Button btn_preview = new Button("预览图片");
 88         btn_preview.setOnAction(this::btnPreview);
 89         /* 窗口抖动 */
 90         Button btn_shake = new Button("窗口抖动");
 91         btn_shake.setOnAction(this::btnShake);
 92         /* 按钮大小 */
 93         btn_send.setPrefSize(70, 30);
 94         btn_close.setPrefSize(70, 30);
 95         /* 按钮的位置 */
 96         AnchorPane.setTopAnchor(btn_close, 350.0);
 97         AnchorPane.setLeftAnchor(btn_close, 0.0);
 98         AnchorPane.setTopAnchor(btn_send, 350.0);
 99         AnchorPane.setLeftAnchor(btn_send, 330.0);
100         AnchorPane.setTopAnchor(btn_img, 224.0);
101         AnchorPane.setLeftAnchor(btn_img, 100.0);
102         AnchorPane.setTopAnchor(btn_preview, 224.0);
103         AnchorPane.setLeftAnchor(btn_preview, 160.0);
104         AnchorPane.setTopAnchor(btn_shake, 224.0);
105         AnchorPane.setLeftAnchor(btn_shake, 220.0);
106 
107         AnchorPane.setTopAnchor(lb_net, 20.0);
108         AnchorPane.setLeftAnchor(lb_net, 420.0);
109         AnchorPane.setTopAnchor(tf_name, 20.0);
110         AnchorPane.setLeftAnchor(tf_name, 470.0);
111 
112         VBox vb = new VBox(pane_01, pane_02);
113 
114         AnchorPane apane = new AnchorPane(vb, btn_send, btn_close, btn_img, btn_preview, btn_shake, lb_net, tf_name);
115         apane.setStyle("-fx-background-color:#FFE4C4");// 设置背景色
116         Scene scene = new Scene(apane);
117 
118         s.setOnCloseRequest(event -> {
119             Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
120             alert.setTitle("退出");
121             alert.setHeaderText("你是否要退出?");
122             Optional<ButtonType> result = alert.showAndWait();
123             if (result.get() == ButtonType.OK) {
124                 try {
125                     socket.leaveGroup(ia);
126                     System.exit(0);
127                 } catch (IOException e) {
128                     e.printStackTrace();
129                 }
130             } else {
131                 event.consume();
132             }
133         });
134         s.setTitle("JDR的午夜群聊");
135         s.setScene(scene);
136         s.setHeight(450);
137         s.setWidth(650);
138         s.show();
139     }
140 
141     /* 窗口抖动 */
142     public void btnShake(ActionEvent enent) {
143 
144         try {
145             String msg = "shake";
146             DatagramPacket p = new DatagramPacket(msg.getBytes(), msg.getBytes().length, ia, 6760);
147             socket.send(p);
148         } catch (IOException e) {
149             // TODO 自动生成的 catch 块
150             e.printStackTrace();
151         }
152     }
153 
154     /* 发送按钮事件 */
155     public void btnSend(ActionEvent enent) {
156         try {
157             String msg = ta_2.getText();
158             DatagramPacket p = new DatagramPacket(msg.getBytes(), msg.getBytes().length, ia, 6760);
159             socket.send(p);
160         } catch (IOException e) {
161             // TODO 自动生成的 catch 块
162             e.printStackTrace();
163         }
164     }
165 
166     /* 关闭按钮事件 */
167     public void btnClose(ActionEvent event) {
168         Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
169         alert.setTitle("退出");
170         alert.setHeaderText("你是否要退出");
171         Optional<ButtonType> result = alert.showAndWait();
172         if (result.get() == ButtonType.OK) {
173             System.exit(0);
174         } else {
175             event.consume();
176         }
177     }
178 
179     /* 发送图片按钮事件 */
180     public void btnImg(ActionEvent event) {
181         FileChooser fileChooser = new FileChooser();
182         fileChooser.setTitle("选择你要查看的文件");
183         File file = fileChooser.showOpenDialog(null);
184         if (file != null) {
185             InputStream in = null;
186             byte data[] = new byte[5];
187             // 读取图片字节数组
188             try {
189                 in = new FileInputStream(file);
190                 data = new byte[in.available()];
191                 in.read(data);
192                 in.close();
193             } catch (IOException e) {
194                 e.printStackTrace();
195             }
196 
197             try {
198                 /* 发送消息,告诉别人你发了图片 */
199                 String str = tf_name.getText() + "说:我给你发了张图片";
200                 DatagramPacket p1 = new DatagramPacket(str.getBytes(), str.getBytes().length, ia, 6760);
201                 socket.send(p1);
202                 // 对字节数组Base64编码
203                 BASE64Encoder encoder = new BASE64Encoder();
204                 socket2 = new MulticastSocket(6770);
205                 DatagramPacket p2 = new DatagramPacket(encoder.encode(data).getBytes(),
206                         encoder.encode(data).getBytes().length, ia, 6770);
207                 socket2.joinGroup(ia);
208                 socket2.send(p2);
209             } catch (IOException e) {
210                 e.printStackTrace();
211             }
212         }
213     }
214 
215     public void btnPreview(ActionEvent event) {
216         FileChooser fileChooser = new FileChooser();
217         fileChooser.setTitle("选择你要查看的文件");
218         File file = fileChooser.showOpenDialog(null);
219 
220         if (file != null) {
221             Stage stage = new Stage();
222             BorderPane root = new BorderPane();
223             String path = file.getPath().toString();
224             String str = path.replaceAll("\\\\", "\\\\\\\\");
225             Image image = new Image("file:" + str);
226             ImageView iv = new ImageView();
227             iv.setImage(image);
228             root.setCenter(iv);
229             Scene scene = new Scene(root);
230             stage.setScene(scene);
231             stage.setWidth(400);
232             stage.setHeight(400);
233             stage.show();
234         }
235     }
236 }
237 
238 class Image_recive extends Thread {
239     public void run() {
240         byte[] buf = new byte[5];
241         DatagramPacket recv = new DatagramPacket(buf, buf.length);
242         while (true) {
243             BASE64Decoder decoder = new BASE64Decoder();
244             try {
245                 FX_UDP.socket2.receive(recv);
246                 String str = new String(recv.getData(), 0, recv.getLength());
247                 // Base64解码
248                 byte[] b = decoder.decodeBuffer(str);
249                 for (int i = 0; i < b.length; ++i) {
250                     if (b[i] < 0) {// 调整异常数据
251                         b[i] += 256;
252                     }
253                 }
254                 // 生成png图片
255                 Date day = new Date();
256                 SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
257                 String name = df.format(day);
258                 OutputStream out = new FileOutputStream("D:/(" + name + ").jpg");
259                 out.write(b);
260                 out.flush();
261                 out.close();
262             } catch (Exception e) {
263             }
264         }
265     }
266 }
267 
268 class Private_recive extends Thread {
269     public void run() {
270         byte[] buf = new byte[100];
271         DatagramPacket recv = new DatagramPacket(buf, buf.length);
272         Date day = new Date();
273         SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
274         try {
275             while (true) {
276                 FX_UDP.socket.receive(recv);
277                 String str = new String(recv.getData(), 0, recv.getLength());
278                 /*窗口颤抖*/
279                 if (str.contains("shake")) {
280                     try {
281                         FX_UDP.s1.setX(50);
282                         Thread.sleep(50);
283                         // FX_UDP.s1.centerOnScreen();
284                         FX_UDP.s1.setX(450);
285                     } catch (InterruptedException e) {
286                         // TODO 自动生成的 catch 块
287                         e.printStackTrace();
288                     }
289                     /*接收表情字符串*/
290                 } else if(str.contains("//")){
291                     Platform.runLater(new Runnable(){
292                         public void run(){
293                             Stage stage = new Stage();
294                             BorderPane bp = new BorderPane();
295                             String[]  strs=str.split("//");
296                             String img_name = strs[1];
297                             Image image = new Image("file:表情包/"+img_name+".jpg");
298                             ImageView iv = new ImageView(image);
299                             bp.setCenter(iv);
300                             Scene scene = new Scene(bp);
301                             stage.setTitle("表情");
302                             stage.setScene(scene);
303                             stage.centerOnScreen();
304                             stage.show();
305                         }
306                     });    
307                     /*正常聊天*/
308                 }else {
309                     FX_UDP.ta_1.appendText(df.format(day) + "\n");
310                     FX_UDP.ta_1.appendText(str + "\n");
311                 }
312             }
313         } catch (IOException e1) {
314             System.out.println("接受失败");
315         }
316     }
317 }

验证结果

输入://00//08 中的任何一个字符串

Javafx模拟QQ机制实现发送表情包的功能

上一篇:JavaFX源码分析实战:如何设置窗体标题小图标和任务栏图标


下一篇:JavaFX如何制作鼠标多击事件?