JavaFX 2.0 Fading Status Message

When a user completes an action it’s nice to display a message to show that the action was successful. With JavaFX animations this becomes very easy to do.

The code below displays a message when a button is clicked, and quickly fades away.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
 
package statusflash;
 
import javafx.animation.FadeTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;
 
 
public class StatusFlash extends Application {
 
 
    public static void main(String[] args) {
        Application.launch(args);
    }
 
    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Status Flash");
        BorderPane layout = new BorderPane();
        Scene scene = new Scene(layout, 300, 250);
 
        final TextField text = new TextField("Added 1 Record");        
        final Button btn = new Button();
 
        btn.setText("Show Message");
        layout.setCenter(text);
        layout.setBottom(btn);
 
        btn.setOnAction(new EventHandler<ActionEvent>() {
 
            public void handle(ActionEvent event) {
                flash(btn, text.getText());
            }
        });
 
        primaryStage.setScene(scene);
        primaryStage.show();
    }
 
    public static void flash(Node node, String message) {
        Font font = Font.font("Verdana", FontWeight.NORMAL, 20);
        Color boxColor = Color.GREY;
        Color textColor = Color.WHITE;
        double duration = 800;
        double arcH = 5;
        double arcW = 5;
 
        final Rectangle rectangle = new Rectangle();
        final Text text = new Text(message);
 
 
        double x = 0;
        double y = 0;
        text.setLayoutX(x);
        text.setLayoutY(y);
        text.setFont(font);
        text.setFill(textColor);
 
        Scene scene = node.getScene();
        final Parent p = scene.getRoot();
 
        if (p instanceof Group) 
        {
            Group group = (Group) p;
            group.getChildren().add(rectangle);
            group.getChildren().add(text);
        }
        if (p instanceof Pane) 
        {
            Pane group = (Pane) p;
            group.getChildren().add(rectangle);
            group.getChildren().add(text);
        }
 
        Bounds bounds = text.getBoundsInParent();
 
        double sWidth = scene.getWidth();
        double sHeight = scene.getHeight();
 
        x = sWidth / 2 - (bounds.getWidth() / 2);
        y = sHeight / 2 - (bounds.getHeight() / 2);
        text.setLayoutX(x);
        text.setLayoutY(y);
        bounds = text.getBoundsInParent();
        double baseLineOffset = text.getBaselineOffset();
 
 
        rectangle.setFill(boxColor);
        rectangle.setLayoutX(x - arcW);
        rectangle.setLayoutY(y - baseLineOffset - arcH);
        rectangle.setArcHeight(arcH);
        rectangle.setArcWidth(arcW);
        rectangle.setWidth(bounds.getWidth() + arcW * 2);
        rectangle.setHeight(bounds.getHeight() + arcH * 2);
 
        FadeTransition ft = new FadeTransition(
                Duration.millis(duration), rectangle);
        ft.setFromValue(1.0);
        ft.setToValue(0.0);
        ft.play();
        ft.setOnFinished(new EventHandler<ActionEvent>() {
 
            public void handle(ActionEvent event) {
                if (p instanceof Group) {
                    Group group = (Group) p;
                    group.getChildren().remove(rectangle);
                    group.getChildren().remove(text);
                }
                 if (p instanceof Pane) {
                    Pane group = (Pane) p;
                    group.getChildren().remove(rectangle);
                    group.getChildren().remove(text);
                }
            }
        });
        FadeTransition ft2 = new FadeTransition(
                Duration.millis(duration + (duration * .1)), text);
        ft2.setFromValue(1.0);
        ft2.setToValue(0.0);
        ft2.play();
    }
}

JavaFX 2.0 Layout with MigPane

I have been starting to look at JavaFX 2.0 since I have been doing a lot of GUI work in swing.

The first challenge was layout since it is different from swing. JavaFX comes with a number of Panes (or panels) to layout your display. They are all pretty basic except for GridPane. GridPane reminds me of GridBagLayout, which is difficult to work with.

Fortunately there is a port of MiGLayout called MigPane. Below is a simple example of using MigPane to build a screen that will grow with a window.

You will need to download MigLayout and the MigPane wrapper.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package miglayoutexample;
 
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;
import org.tbee.javafx.scene.layout.MigPane;
 
public class MigLayoutExample extends Application 
{
    public static void main(String[] args) {
        Application.launch(args);
    }
 
    private Button newBtn;
    private Button prevBtn;
    private Button nextBtn;
    private TextArea textArea;
 
    @Override
    public void start(Stage primaryStage) 
    {
        primaryStage.setTitle("MigPane example");
        newBtn = new Button("New");
        prevBtn = new Button("<<<<");
        nextBtn = new Button(">>>>");
 
        textArea = new TextArea();
 
        MigPane layout = new MigPane(
            "",                         // Layout Constraints
            "[grow]10[shrink 0]4[shrink 0]",  // Column constraints
            "[][200,grow]");            // Row constraint
 
        layout.add(newBtn);
        layout.add(prevBtn);
        layout.add(nextBtn, "wrap");
 
        layout.add(textArea, "grow,span");
 
        Scene scene = new Scene(layout);        
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}