1 import javafx.animation.KeyFrame;
2 import javafx.animation.Timeline;
3 import javafx.application.Application;
4 import javafx.beans.property.DoubleProperty;
5 import javafx.geometry.Pos;
6 import javafx.scene.Node;
7 import javafx.stage.Stage;
8 import javafx.scene.Scene;
9 import javafx.scene.control.Button;
10 import javafx.scene.control.ScrollBar;
11 import javafx.scene.layout.BorderPane;
12 import javafx.scene.layout.HBox;
13 import javafx.scene.layout.Pane;
14 import javafx.scene.paint.Color;
15 import javafx.scene.shape.Circle;
16 import javafx.util.Duration;
17
18 public class MultipleBounceBall extends Application {
19 @Override
20 public void start(Stage primaryStage) {
21 MultipleBallPane ballPane = new MultipleBallPane();
22 ballPane.setStyle("-fx-border-color: yellow");
23
24 Button btAdd = new Button("+");
25 Button btSubtract = new Button("-");
26 HBox hBox = new HBox(10);
27 hBox.getChildren().addAll(btAdd, btSubtract);
28 hBox.setAlignment(Pos.CENTER);
29
30
31 btAdd.setOnAction(e -> ballPane.add());
32 btSubtract.setOnAction(e -> ballPane.subtract());
33
34
35 ballPane.setOnMousePressed(e -> ballPane.pause());
36 ballPane.setOnMouseReleased(e -> ballPane.play());
37
38
39 ScrollBar sbSpeed = new ScrollBar();
40 sbSpeed.setMax(20);
41 sbSpeed.setValue(10);
42 ballPane.rateProperty().bind(sbSpeed.valueProperty());
43
44 BorderPane pane = new BorderPane();
45 pane.setCenter(ballPane);
46 pane.setTop(sbSpeed);
47 pane.setBottom(hBox);
48
49
50 Scene scene = new Scene(pane, 250, 150);
51 primaryStage.setTitle("MultipleBounceBall");
52 primaryStage.setScene(scene);
53 primaryStage.show();
54 }
55
56 private class MultipleBallPane extends Pane {
57 private Timeline animation;
58
59 public MultipleBallPane() {
60
61 animation = new Timeline(
62 new KeyFrame(Duration.millis(50), e -> moveBall()));
63 animation.setCycleCount(Timeline.INDEFINITE);
64 animation.play();
65 }
66
67 public void add() {
68 Color color = new Color(Math.random(),
69 Math.random(), Math.random(), 0.5);
70 getChildren().add(new Ball(30, 30, 20, color));
71 }
72
73 public void subtract() {
74 if (getChildren().size() > 0) {
75 getChildren().remove(getChildren().size() - 1);
76 }
77 }
78
79 public void play() {
80 animation.play();
81 }
82
83 public void pause() {
84 animation.pause();
85 }
86
87 public void increaseSpeed() {
88 animation.setRate(animation.getRate() + 0.1);
89 }
90
91 public void decreaseSpeed() {
92 animation.setRate(
93 animation.getRate() > 0 ? animation.getRate() - 0.1 : 0);
94 }
95
96 public DoubleProperty rateProperty() {
97 return animation.rateProperty();
98 }
99
100 protected void moveBall() {
101 for (Node node: this.getChildren()) {
102 Ball ball = (Ball)node;
103
104 if (ball.getCenterX() < ball.getRadius() ||
105 ball.getCenterX() > getWidth() - ball.getRadius()) {
106 ball.dx *= -1;
107 }
108 if (ball.getCenterY() < ball.getRadius() ||
109 ball.getCenterY() > getHeight() - ball.getRadius()) {
110 ball.dy *= -1;
111 }
112
113
114 ball.setCenterX(ball.dx + ball.getCenterX());
115 ball.setCenterY(ball.dy + ball.getCenterY());
116 }
117 }
118 }
119
120 class Ball extends Circle {
121 private double dx = 1, dy = 1;
122
123 Ball(double x, double y, double radius, Color color) {
124 super(x, y, radius);
125 setFill(color);
126 }
127 }
128
129
133 public static void main(String[] args) {
134 launch(args);
135 }
136 }