Very Basic JavaFX 2.0 Component

I work a lot with Swing and one of the more common tasks is creating a custom component. This usually involves some custom drawing.

Here is a quick example of a component that displays a black circle. Very basic, but it will re-size if the panels bounds change.

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
public class SwingClock extends JPanel{
 
  @Override
  public void paintComponent(Graphics g)
  {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D)g.create();
    Dimension size = getSize();
    int w = size.width;
    int h = size.height;
    int r = w;
    if(h < r)
      r = h;
    int x = 0;
    int y = 0;
    g2d.setColor(Color.BLACK);
    g2d.fillOval(x, y, r, r);
    g2d.dispose();
  }
 
  public static void main(String[] args) throws Exception
  {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    SwingClock clock = new SwingClock();
    frame.getContentPane().setLayout(new BorderLayout());
    frame.getContentPane().add(clock,BorderLayout.CENTER);
    frame.setSize(200,200);
    frame.setVisible(true);
  }
}

Now how is this done in JavaFX 2..0? Well it’s a bit more work.

You will need three classes 1. The Control, 2. The Control Skin, and 3. The stage.

First up is the Control, this will contain the model for our control. Because it does not really do anything the we only need to set the skin and define the max width and height. This is so the control will grow along with the frame.

1
2
3
4
5
6
7
8
9
public class Clock extends Control implements Skinnable
{
  public Clock()
  {
    setSkin(new ClockSkin(this));
    setMaxHeight(Double.MAX_VALUE);
    setMaxWidth(Double.MAX_VALUE);
  }
}

Next up is the Skin. The skin provides the Node used to display this control. It’s important to use the StackPane as the returned node as it will allow you to add overlapping nodes if you want.

getNode is only called when the parent had changed. So it’s ok to do some adjustments here.

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
public class ClockSkin implements Skin
{
  private Clock skinable;
  private StackPane root;
  private Circle cirlce;
 
  public ClockSkin(Clock clock)
  {
    skinable = clock;
    root = new StackPane();
    cirlce = new Circle();
    cirlce.setFill(Color.BLACK);
    root.getChildren().add(cirlce);
  }
 
  @Override
  public void dispose()
  {
  }
 
  @Override
  public Node getNode() {
    double w = skinable.getWidth();
    double h = skinable.getHeight();
    cirlce.setCenterX(w/2);
    cirlce.setCenterY(h/2);
    double r = w;
    if(h < r)
      r = h;
    cirlce.setRadius(r/3);
    return root;
  }
 
  @Override
  public Clock getSkinnable() {
    return skinable;
  }}

This is just a basic JavaFX startup code that every applications needs.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class FirstComponent extends Application {
 
  public static void main(String[] args) {
    launch(args);
  }
 
  @Override
  public void start(Stage primaryStage) {
    primaryStage.setTitle("First Component");
    Clock clock = new Clock();
    StackPane root = new StackPane();
    root.getChildren().add(clock);
    primaryStage.setScene(new Scene(root, 300, 250));
    primaryStage.show();
  }
}

That should be it! Now you have a very basic control on which to build something more advanced.

https://github.com/robmayhew/learning-javafx-2.0

Posted in Uncategorized | Leave a comment

Java Quick Data Store

I’ve written a small library to quickly save and load data in a Java app. It’s a simple persistent data store. I plan to use it in some upcoming demos.

Example:


QDS.save("Testing", "A String");
String s = (String)QDS.load("Testing");

Downlaod src

Posted in Uncategorized | Leave a comment

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();
    }
}
Posted in Uncategorized | 1 Comment

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();
    }
}
Posted in Uncategorized | 2 Comments

Javascript Style Guide

Google has a style guide for writing javascript. I think it’s great. Link

Posted in Uncategorized | Leave a comment