2012-03-23 JavaFX 2.0 第7歩
■[Java][JavaFX]JavaFX 2.0でアプリケーション作成(その6)
少し間が空きましたが、id:torutk:20120316の続きです。
次は前回の画面です。tryAcquireボタンを押すと、ボタン右横にtryAcquire結果としてtrueまたはfalseの文字列を表示します。tryAcquireボタンを繰り返し押し、tryAcquire結果が前と変わらないとき、結果の文字列が変化しないため、tryAcquire処理が実際に実行されたかどうかが見た目には分かりません。
ユーザーインタフェースとして、ユーザー操作に対する直接的なフィードバックがないことになり、好ましい設計ではありませんでした。
そこで、tryAcquireボタンを押すときに、いったん前回の結果(trueまたはfalse)を消去し、再度表示することにします。
しかし、前回のコードにもあるように、ボタンが押されたイベントハンドラーの中でclear()するだけでは、消去した状態が見た目に分からず、修正前と同じになってしまいます。
tryButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
resultField.clear();
boolean acquired = semaphore.tryAcquire();
resultField.setText(String.valueOf(acquired));
updatePermits();
}
});
そこで、SwingにはないJavaFXの新しい概念であるTransitionを使って、tryAcquire結果をフェードイン表示することにします。フェードインまたはフェードアウト効果を実現するFadeTransitionクラスを使用します。
tryAcquire結果表示部品をTextFieldからTextに変更
前回までに作ったアプリケーションでは、tryAcquireの結果を表示するのにTextFieldを使用していますが、TextFieldをFadeTransitionに喰わせると、枠線もフェードしてしまいます。TextFieldの中のテキストだけフェードさせたかったのですが、実装方法が分からなかったので、TextFieldをやめてTextを使うことにしました。枠線なしでテキスト表示だけになります。
- フィールドの定義
private Text resultText;
- 初期化
resultText = new Text();
semaphorePane.add(resultText, 1, 1);
- releaseボタンを押した際のイベントハンドラ
releaseButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
semaphore.release();
resultText.setText("");
updatePermits();
}
});
clear()メソッドがないので、空文字列をセットしています。
- tryAcquireボタンを押した際のイベントハンドラ
tryButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
boolean acquired = semaphore.tryAcquire();
updateTryResult(acquired);
updatePermits();
}
});
新たにメソッド void updateTryResult(boolean) を定義し、これを呼び出すようにしています。
FadeTransitionの実装
tryAcquireボタンが押された際に呼び出されるイベントハンドラの中で、結果テキスト(resultText)にフェードイン効果を付けて文字列を表示する処理を、updateTryResultメソッドに記述します。
private void updateTryResult(final boolean acquired) {
resultText.setText(String.valueOf(acquired));
FadeTransition fader = new FadeTransition(Duration.millis(1000), resultText);
fader.setFromValue(0.0);
fader.setToValue(1.0);
fader.play();
}
まず、結果テキスト(resultText)に新しい文字列をセットします。
次に、FadeTransitionインスタンスを生成し、フェード効果を行う時間、フェード効果対象Nodeを指定します。
フェード効果の開始時点の透過度をsetFromValueメソッドで指定します。
フェード効果の終了時点の透過度をsetToValueメソッドで指定します。
フェードイン効果の場合は、開始時点の透過度を0.0(完全に透過するので表示が見えない)を、終了時点の透過を1.0(完全に不透過なので表示が指定した色で見える)を指定します。フェードアウト効果の場合はこの逆にします。
FadeTransitionインスタンスのplayメソッドを呼び、フェード効果を発動します。
画面動作
以下にFlashで画面の操作を録画した動画を置いています。
ソースコード全体
今回のソースコード全体を次に示します。
package semaphoreview; import java.util.concurrent.Semaphore; import javafx.animation.FadeTransition; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.layout.BorderPane; import javafx.scene.layout.GridPane; import javafx.scene.text.Text; import javafx.stage.Stage; import javafx.util.Duration; /** * セマフォの動きを理解するための可視化プログラムメイン。 * @author toru */ public class SemaphoreView extends Application { private Semaphore semaphore = new Semaphore(1); private TextField permitsField; private Text resultText; /** * @param args the command line arguments */ public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("Semaphoreの動きを理解する"); BorderPane borderPane = new BorderPane(); Label topLabel = new Label("Semaphoreへの操作とその結果"); topLabel.setStyle("-fx-background-color: mistyrose"); BorderPane.setAlignment(topLabel, Pos.CENTER); BorderPane.setMargin(topLabel, new Insets(6)); borderPane.setTop(topLabel); GridPane semaphorePane = new GridPane(); //semaphorePane.setGridLinesVisible(true); semaphorePane.setHgap(10); semaphorePane.setVgap(16); Label permitsLabel = new Label("利用可能な許可数:"); semaphorePane.add(permitsLabel, 0, 0); permitsField = new TextField(); semaphorePane.add(permitsField, 1, 0); Button tryButton = new Button("Try acquire"); tryButton.setMaxWidth(Double.MAX_VALUE); tryButton.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { boolean acquired = semaphore.tryAcquire(); updateTryResult(acquired); updatePermits(); } }); semaphorePane.add(tryButton, 0, 1); resultText = new Text(); semaphorePane.add(resultText, 1, 1); Button releaseButton = new Button("Release"); releaseButton.setMaxWidth(Double.MAX_VALUE); releaseButton.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { semaphore.release(); resultText.setText(""); updatePermits(); } }); semaphorePane.add(releaseButton, 0, 2); BorderPane.setMargin(semaphorePane, new Insets(4, 12, 4, 12)); borderPane.setCenter(semaphorePane); updatePermits(); primaryStage.setScene(new Scene(borderPane, 300, 200)); primaryStage.show(); } private void updateTryResult(final boolean acquired) { resultText.setText(String.valueOf(acquired)); FadeTransition fader = new FadeTransition(Duration.millis(1000), resultText); fader.setFromValue(0.0); fader.setToValue(1.0); fader.play(); } private void updatePermits() { permitsField.setText(String.valueOf(semaphore.availablePermits())); } }
記事一覧
- 464 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=11&ved=0CCcQFjAAOAo&url=http://d.hatena.ne.jp/torutk/20100701/p1&ei=581sT_qlE-HsmAWssqiMBg&usg=AFQjCNG8V2Mz0nQ0UZUvsY4s8oGsosDwLA
- 225 http://pipes.yahoo.com/pipes/pipe.info?_id=c9113ed44cd419a8abf321af5421a967
- 169 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&ved=0CC8QFjAB&url=http://d.hatena.ne.jp/torutk/20110627/p1&ei=y2xtT4mJCqiWiQeL3I39BQ&usg=AFQjCNHFrMLiaGRw14iLbofca5ydCP042g&sig2=l-f_tuwesXy0tXj75DSNQQ
- 120 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&ved=0CEAQFjAC&url=http://d.hatena.ne.jp/torutk/20101009/p1&ei=GcdsT-m4Mc-4iAfT3sz3BQ&usg=AFQjCNHrDZs9MyuiAZjY0K_OOE1e9eZ0-g&sig2=zbcUg2EasavCe074nUwrpQ
- 117 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&frm=1&source=web&cd=2&ved=0CDwQFjAB&url=http://d.hatena.ne.jp/torutk/20100927/p1&ei=9DZtT8CgE4yyiQe71cTyBQ&usg=AFQjCNHft5uV0RP7S7pV6REHVUAX0lzeZQ&sig2=zw3Wfw-F6xGXIv6jVWbiFQ
- 112 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=4&ved=0CEgQFjAD&url=http://d.hatena.ne.jp/torutk/20070513/p2&ei=UcdsT57NAePImQW3nKG4Bg&usg=AFQjCNHr_1n1i7pz3xCiQnmJ8aDWC-9d2Q&sig2=xymVhEBMGrDC9OpTgMh1Rw
- 95 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=5&ved=0CFQQFjAE&url=http://d.hatena.ne.jp/torutk/20090628/p1&ei=v0FtT8zVNcfymAXi8MGdBg&usg=AFQjCNHyZyAxxca1q9KUTDDjc_ykHBjXdA&sig2=hCuWK0ykOMOkmKQs2NuyrQ
- 54 http://tochi-gis.cocolog-nifty.com/blog/2008/10/eclipse-ide-for.html
- 46 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=6&ved=0CFIQFjAF&url=http://d.hatena.ne.jp/torutk/20080103/p1&ei=58NsT4eLCbGTiAfK6fD6BQ&usg=AFQjCNEmVGOKfHP9wkzhwWE_E9wZEi6GpQ&sig2=CZpieKTTrLgXeAhInzRgHA
- 36 http://www.google.co.jp/url?sa=t&rct=j&q=visual studio 2010 express sp1&source=web&cd=8&sqi=2&ved=0CGEQFjAH&url=http://d.hatena.ne.jp/torutk/20100927/p1&ei=AQ9tT-rALuzTmAWksoWYBg&usg=AFQjCNHft5uV0RP7S7pV6REHVUAX0lzeZQ&sig2=CaIJZQBJXeiM
