Javafx给聊天室添加窗口抖动的功能

我想把QQ上的功能都在自己的聊天室上实现,不出意外,会一直更新。

目标:通过点击窗口抖动的按钮,实现给对方发送窗口抖动的效果。

个人想法:点击窗口抖动的时候,发送一段特殊字符,让其他聊天室的线程的socket接收到。将接收到的字符串进行一个判断,看是否含有点击窗口抖动后发送的字符串,如果有,则开始抖动。

抖动的定义及实现:抖动实际上就是聊天室的位置在屏幕中发生了偏移。因此可以通过改变stage的位置,也就是通过setX()或者setY()这个方法去改变聊天是的位置。从而实现窗口抖动的功能。

添加btn_shake按钮:

1 Button btn_shake = new Button("窗口抖动");
2 btn_shake.setOnAction(this::btnShake);
3 /*btn_shake的位置*/
4 AnchorPane.setTopAnchor(btn_shake, 224.0);
5 AnchorPane.setLeftAnchor(btn_shake, 220.0);

btnShake()方法实现:

 1 public void btnShake(ActionEvent enent) {
 2         try {
 3             String msg = "shake";
 4             DatagramPacket p = new DatagramPacket(msg.getBytes(), msg.getBytes().length, ia, 6760);
 5             socket.send(p);
 6         } catch (IOException e) {
 7             // TODO 自动生成的 catch 块
 8             e.printStackTrace();
 9         }
10     }

线程监听判断是否要抖动:

 1 if (str.contains("shake")) {
 2     try {
 3         FX_UDP.s1.setX(50);
 4         Thread.sleep(50);
 5         // FX_UDP.s1.centerOnScreen();
 6         FX_UDP.s1.setX(450);
 7     } catch (InterruptedException e) {
 8         // TODO 自动生成的 catch 块
 9         e.printStackTrace();
10     }
11 }

完整代码如下:

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

实验验证:

实现了窗口抖动,但是本人不会弄动态图。卑微了。

唯一缺陷:FX_UDP.s1.centerOnScreen();使用这个将stage居中会报异常。

猜你喜欢

转载自www.cnblogs.com/jdr-gbl/p/12056107.html