JavaFX Abacus Tutorial, Part II
This is the second part of a basic tutorial on JavaFX. The first part can be found here and the code is on github. The running example of the tutorial is to build an abacus. If you are curious how the final solution will look like, please
have look at this 7 min video.
Your latest homework assignment was to extend the single-circle-version to a board of 10 * 10 circles.
Have you done it? Cool.
When starting you should now see something like
.
You should now be familiar with how to create a simple JavaFX application, how to use the SceneGraph, adding child nodes, and using builders.
Today, we will introduce event handling and translation.
Each node in the SceneGraph can be transformed in various ways by translation, rotation, scaling, and more.
What we need for the movement is a translation, which is a transformation that displays the node at a given x/y offset from its original position.
Setting the translation is easy. Simply change the translateX property of the node.
|
1 |
circle.setTranslateX(100); |
will display the node 100 pixels to right from its original position.
Unlike Swing, there is no need to clear the canvas and repaint all nodes on the new position! Changing the translateX property is all it takes. The SceneGraph takes care of proper repainting.
Let’s say we want the circles in our abacus to move 100 pixel to the right when we click on it. This requires an event handler on the circle that changes the translateX value. Here is how you set such an event handler as an anonymous inner class:
|
1 2 3 4 5 |
circle.setOnMouseClicked(new EventHandler<MouseEvent>() { public void handle(MouseEvent mouseEvent) { circle.setTranslateX(100); } }); |
As an optimization of the above, you can share one event handler between all the circles. In this case use
1 mouseEvent.getSource().setTranslateX(100);
The full code now looks like so:
|
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 |
package solution; import javafx.application.Application; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.input.MouseEvent; import javafx.scene.layout.Pane; import javafx.scene.shape.Circle; import javafx.scene.shape.CircleBuilder; import javafx.stage.Stage; public class Abacus_2_Add_all_balls_and_onClick extends Application { private static final int ROW_COUNT = 10; private static final int COL_COUNT = 10; private static final int RADIUS = 20; private static final int DIAMETER = 2 * RADIUS; private static final int WIDTH = COL_COUNT * DIAMETER; private static final int HEIGHT = ROW_COUNT * DIAMETER; private static final int MOVE_WAY = 100; @Override public void start(Stage primaryStage) { primaryStage.setTitle("JavaFX Abacus"); Pane root = new Pane(); for (int row = 0; row < ROW_COUNT; row++) { for (int column = 0; column < COL_COUNT; column++) { final Circle circle = makeCircle(row, column); root.getChildren().add(circle); onClick(circle); } } primaryStage.setScene(new Scene(root, WIDTH + MOVE_WAY, HEIGHT)); primaryStage.show(); } private void onClick(final Circle circle) { circle.setOnMouseClicked(new EventHandler<MouseEvent>() { public void handle(MouseEvent mouseEvent) { circle.setTranslateX(MOVE_WAY); } }); } private Circle makeCircle(int row, int column) { return CircleBuilder.create() .radius (RADIUS - 1) .centerX(RADIUS + (column * DIAMETER)) .centerY(RADIUS + (row * DIAMETER)) .build(); } public static void main(String[] args) { launch(args); } } |
Clicking on a circle now moves it to the right “on its rail”.

Homework
Your homework assignment is to make the circle moving back to its
original position (translateX becomes 0) when you click on a circle
that has been moved before.
Next week, we will animate the movements.
Finally
If you are committed to learn JavaFX, please consider joining one of our JavaFX workshops at Canoo.
See you next time!
Dierk König
P.S. Tim Yates has posted a GroovyFX version.













Hamlet D'Arcy said,
January 16, 2013 @ 8:16
This black and white abacus reminds me of some classic optical illusions, like this one: http://www.illusions.org/dp/1-2.htm
I’d love to see a small JavaFX project that implements a bunch of the illusions from that sight… maybe at the next Hackergarten?