Server Event Client Sample
JavaFX Advent Calendar 2015 - Qiitaの13日目です。
昨日は@skrbさんのJavaFX と Project Jigsaw - JavaFX in the Boxでした。
明日は@Yucchi_jpさんです。
前回Server Sent Event のサーバー処理についてちょっと実装を試したJava EEエヴァンジェリストによる!EE 8最新動向!に行ってきました! - tomoTakaの日記のですが、クライアントもJavaで実装できると紹介されていたので、JavaFXでサーバーから受信したレスポンスをアニメーションで表現してみるのに挑戦しました。
ですが、そもそもアニメーションがよくわかっていなくて、、、
2パターンの実装は、ここChapter 15. Server-Sent Events (SSE) Supportを参考にしました。
画面
リクエスト送信ボタンをクリックした後、指定したタスク数の「Task0〜5の結果」ラベルが左(サーバー)から右(クライアント)へタスク処理時間で指定した時間の間隔で移動します。
「リクエスト送信(非同期)」ボタンの処理は思ってようにアニメーションしますが、「リスエスト送信(同期)」ボタンの処理は、アニメーションで複数のラベルが同時になってしまいます???
- 初期表示時
- リスエスト送信(非同期)ボタンクリック後
実装
- 非同期処理
アニメーションの部分はコメントいただいて修正しています。
@FXML private void requestAction2(ActionEvent event){ listeningProperty.setValue(Boolean.TRUE); disableProperty.setValue(Boolean.FALSE); int taskCntVal = taskCnt.getValue(); int taskIntervalVal = taskInterval.getValue(); String url = "http://localhost:8080/event/" + taskCntVal + "/" + taskIntervalVal; Client client = ClientBuilder.newBuilder().register(SseFeature.class).build(); WebTarget target = client.target(url); eventSource = EventSource.target(target).build(); eventSource.register(inboundEvent ->{ String data = inboundEvent.readData(String.class); int id = Integer.parseInt(inboundEvent.getId()); Label label = labels[id]; TranslateTransition t = transitions[id]; // **サーバーより受信したIDで実行するアニメーションを設定 Platform.runLater(()->{ label.setText(data); // **ラベルにサーバーより受信した結果を設定 new Timeline(new KeyFrame(Duration.millis(500), e-> t.play())).play(); / **アニメーション開始 }); }, "message-client"); eventSource.open(); }
修正後
Platform.runLater(()->{ label.setText(data); TranslateTransition t = new TranslateTransition(Duration.millis(300), label); t.setFromX(0); t.setToX(-200); t.play(); // **アニメーション開始 });
- 同期処理
@FXML private void requestAction1(ActionEvent event) { listeningProperty.setValue(Boolean.TRUE); disableProperty.setValue(Boolean.FALSE); Arrays.stream(labels).forEach(l -> l.setText(null)); int taskCntVal = taskCnt.getValue(); int taskIntervalVal = taskInterval.getValue(); String url = "http://localhost:8080/event/" + taskCntVal + "/" + taskIntervalVal; Client client = ClientBuilder.newBuilder().register(SseFeature.class).build(); WebTarget target = client.target(url); EventInput eventInput = target.request().get(EventInput.class); while (!eventInput.isClosed()){ InboundEvent inboundEvent = eventInput.read(); if (inboundEvent == null){ break; } int id = Integer.parseInt(inboundEvent.getId()); Label label = labels[id]; String data = inboundEvent.readData(String.class); label.setText(data); TranslateTransition t = transitions[id]; new Timeline(new KeyFrame(Duration.millis(500), e-> t.play())).play(); } }
- 初期処理
アニメーションの初期設定など
@Override public void initialize(URL url, ResourceBundle rb) { labels = new Label[] {label1, label2, label3, label4, label5}; Arrays.stream(labels).forEach(l -> l.setText(null)); transitions = new TranslateTransition[]{ new TranslateTransition(Duration.millis(500), label1) ,new TranslateTransition(Duration.millis(500), label2) ,new TranslateTransition(Duration.millis(500), label3) ,new TranslateTransition(Duration.millis(500), label4) ,new TranslateTransition(Duration.millis(500), label5) }; Arrays.stream(transitions).forEach(t -> { t.setFromX(0); t.setToX(-200); }); // Buttonの使用制御 listeningProperty = new SimpleBooleanProperty(false); startBtn1.disableProperty().bind(listeningProperty); startBtn2.disableProperty().bind(listeningProperty); disableProperty = new SimpleBooleanProperty(true); closeBtn.disableProperty().bind(disableProperty); }
実装はここtomoTaka01/SseClientSample: Server Sent Eve... - GitHubにアップしています。
JavaFXの問題ではないのですが、非同期処理を実行するとサーバーへ何度もリクエスト送信されてしまいます?(汗)
すごく中途半端な状態で申し訳ないですが、アドバイスいただければ幸いです、、、
アニメーション難しいです、まだまだ勉強不足です、、、