diff --git a/README.md b/README.md
index 84dcea5..4c11789 100644
--- a/README.md
+++ b/README.md
@@ -158,7 +158,7 @@ Indicates 100% completion of all exercises for that chapter
Chapter 15
- Event-Driven Programming and Animations
-Exercises Needed: 25,27,31,33,35
+Exercises Needed: 33,35
Chapter
diff --git a/ch_15/Exercise15_27.java b/ch_15/Exercise15_27.java
new file mode 100644
index 0000000..dcc1b01
--- /dev/null
+++ b/ch_15/Exercise15_27.java
@@ -0,0 +1,36 @@
+package ch_15;
+
+import javafx.animation.PathTransition;
+import javafx.animation.Timeline;
+import javafx.application.Application;
+import javafx.scene.Scene;
+import javafx.scene.layout.Pane;
+import javafx.scene.shape.Line;
+import javafx.scene.text.Text;
+import javafx.stage.Stage;
+import javafx.util.Duration;
+
+/**
+ * *15.27 (Control a moving text) Write a program that displays a moving text, as shown
+ * in Figure 15.33a and b. The text moves from left to right circularly. When it
+ * disappears in the right, it reappears from the left. The text freezes when the
+ * mouse is pressed and moves again when the button is released.
+ */
+public class Exercise15_27 extends Application {
+ @Override
+ public void start(Stage primaryStage) {
+ Pane pane = new Pane();
+ Text text = new Text("Programing is fun");
+ pane.getChildren().add(text);
+ PathTransition pt = new PathTransition(Duration.millis(10000),
+ new Line(-50, 50, 250, 50), text);
+ pt.setCycleCount(Timeline.INDEFINITE);
+ pt.play();
+ pane.setOnMousePressed(e -> pt.pause());
+ pane.setOnMouseReleased(e -> pt.play());
+ Scene scene = new Scene(pane, 200, 100);
+ primaryStage.setTitle("Exercise_15_27");
+ primaryStage.setScene(scene);
+ primaryStage.show();
+ }
+}
\ No newline at end of file
diff --git a/ch_15/Exercise15_31.java b/ch_15/Exercise15_31.java
new file mode 100644
index 0000000..06c236a
--- /dev/null
+++ b/ch_15/Exercise15_31.java
@@ -0,0 +1,109 @@
+package ch_15;
+
+import javafx.animation.PathTransition;
+import javafx.application.Application;
+import javafx.scene.Scene;
+import javafx.scene.layout.Pane;
+import javafx.scene.paint.Color;
+import javafx.scene.shape.Arc;
+import javafx.scene.shape.Circle;
+import javafx.scene.shape.Line;
+import javafx.stage.Stage;
+import javafx.util.Duration;
+
+/**
+ * **15.31 (Geometry: pendulum) Write a program that animates a pendulum swinging,
+ * as shown in Figure 15.35. Press the UP arrow key to faster the speed and the
+ * DOWN key to slower it. Press the S key to stop animation and the R key to
+ * resume it.
+ */
+public class Exercise15_31 extends Application {
+ private final double sceneWidth = 400;
+
+ private final double sceneHeight = 400;
+
+ @Override
+ public void start(Stage primaryStage) throws Exception {
+ PendulumPane pendulumPane = new PendulumPane(sceneWidth, sceneHeight);
+ Scene scene = new Scene(pendulumPane, sceneWidth, sceneHeight);
+ primaryStage.setTitle(getClass().getName());
+ primaryStage.setScene(scene);
+ primaryStage.show();
+
+ pendulumPane.play();
+
+ scene.setOnKeyPressed(e -> {
+ switch (e.getCode()) {
+ case UP:
+ pendulumPane.faster();
+ break;
+ case DOWN:
+ pendulumPane.slower();
+ break;
+ }
+ });
+ }
+}
+
+class PendulumPane extends Pane {
+ PathTransition animationPath;
+ Circle referenceCircleTop;
+ Circle referenceCircleBottom;
+ Line shaft;
+ Arc pendulumSwingArc;
+
+ PendulumPane(double width, double height) {
+ setPrefWidth(width);
+ setPrefHeight(height);
+ pendulumSwingArc = new Arc(width / 2,
+ height * 0.8,
+ width * 0.15,
+ width * 0.15,
+ 180,
+ 180);
+ pendulumSwingArc.setFill(Color.TRANSPARENT);
+ pendulumSwingArc.setStroke(Color.BLACK);
+
+ referenceCircleBottom = new Circle(pendulumSwingArc.getCenterX() - pendulumSwingArc.getRadiusX(),
+ pendulumSwingArc.getCenterY(),
+ 10);
+ referenceCircleTop = new Circle(pendulumSwingArc.getCenterX(),
+ pendulumSwingArc.getCenterY() - height / 2,
+ referenceCircleBottom.getRadius() / 2);
+ pendulumSwingArc = new Arc(referenceCircleTop.getCenterX(),
+ referenceCircleTop.getCenterY(),
+ width / 2,
+ height / 2,
+ 240,
+ 60);
+ shaft = new Line(
+ referenceCircleTop.getCenterX(), referenceCircleTop.getCenterY(),
+ referenceCircleBottom.getCenterX(), referenceCircleBottom.getCenterY());
+
+ shaft.endXProperty().bind(referenceCircleBottom.translateXProperty().add(referenceCircleBottom.getCenterX()));
+ shaft.endYProperty().bind(referenceCircleBottom.translateYProperty().add(referenceCircleBottom.getCenterY()));
+ animationPath = new PathTransition();
+ animationPath.setDuration(Duration.millis(4000));
+ animationPath.setPath(pendulumSwingArc);
+ animationPath.setNode(referenceCircleBottom);
+ animationPath.setOrientation(PathTransition.OrientationType.NONE);
+ animationPath.setCycleCount(PathTransition.INDEFINITE);
+ animationPath.setAutoReverse(true);
+
+ getChildren().addAll(referenceCircleBottom, referenceCircleTop, shaft);
+
+ }
+
+ public void play() {
+ animationPath.play();
+ }
+
+
+ public void faster() {
+ animationPath.rateProperty().set(animationPath.getRate() + 1);
+ }
+
+ public void slower() {
+ animationPath.rateProperty().set(animationPath.getRate() - 1);
+ }
+}
\ No newline at end of file