# Lab 4: Introduction to JavaFX
This lab will give you a taste of building your own graphical applications using JavaFX. First you’ll use **`Stages`, `Scenes`, `Panes`, `Rectangles`**, and more to create an application that visually matches our mock-up shown below. Next, you’ll write an **`EventHandler`** that allows your application to respond to user input. Andy’s Graphics lectures will be a useful reference throughout this lab, so be sure to take a look at them ([Graphics 1](https://cs.brown.edu/courses/cs015/lecture/pdf/CS15.Lecture_9_Graphics_Part_I.10.3.24.pdf), [Graphics 2](https://cs.brown.edu/courses/cs015/lecture/pdf/CS15.Lecture_10_Graphics_Part_II.10.8.24.pdf)).
You will be using several built-in classes from Java in this lab, so how will you find all the methods and properties available to use? That’s right, the Javadocs! These Javadocs were written by the Java developers and are frequently used by all coders! There is a convenient link to them on the CS15 website (Resources > Java Documentation > [JavaFX-docs](https://docs.oracle.com/javase/8/javafx/api/)), or choose the first result when you Google “Javafx 8 API”. For this project, most of the classes you will be using are from the [javafx.scene.shape package](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/shape/package-summary.html).
**Goal**: Create a JavaFX application that matches the below mock-up that lets users move one rectangle left and right using their keyboard in order to overlap a target rectangle.
As always, begin this lab by looking over the lab handout!
# Assignment Roadmap
:::info
### [Silly Premise](#Silly-Premise)
## **[Part 1: Building a GUI with JavaFX Panes ](#Part-1:-Building-a-GUI-with-JavaFX-Panes)**
[Getting Started](#Getting-Started)
[Step 0: Reconfiguring IntelliJ](#Step-0:-Reconfiguring-IntelliJ)
[Step 1: Building the GUI](#Step-1:-Building-the-GUI)
[Step 2: Adding Panes](#Step-2:-Adding-Panes)
[Are you there pane?](#Are-you-there-pane?)
[Step 3: Create and Sub-Size Panes](#Step-3:-Create-and-Sub-Size-Panes)
[Step 4: Setting up Button Action](#Step-4:-Setting-up-Button-Action)
[Step 5: Creating and Adding Contents to the Bottom Pane](#Step-5:-Creating-and-Adding-Contents-to-the-Bottom-Pane)
[Step 6: Adding Rectangles](#Step-6:-Adding-Rectangles)
[Overarching Design](#Overarching-Design)
[Now let’s code this design out](#Now-let’s-code-this-design-out)
## **[Part 2: Responding to User Input ](#Part-2:-Responding-to-User-Input)**
[Step 7: Adding an EventHandler for Key Input](#Step-7:-Adding-an-EventHandler-for-Key-Input)
[Focus? What’s that?](#Focus?-What’s-that?)
[Step 8: Customizing your EventHandler](#Step-8:-Customizing-your-EventHandler)
[A Note On Variables](#A-Note-On-Variables)
:::
## Silly Premise
This week Zuko is looking for Aang, but both of them are rectangles. Help Zuko find Aang!
<img style="display: block; margin: auto;" src="https://hackmd.io/_uploads/SkLomLfhC.jpg" alt="Zuko Image">
# Part 1: Building a GUI with JavaFX Panes
<img style="display: block; margin: auto;" src="https://hackmd.io/_uploads/SJs54IGn0.png" alt="Example Image">
## Getting Started
Click [here](https://classroom.github.com/a/Vj3fxZD4) to get the stencil from GitHub - refer to the [CS15 GitHub Guide](https://docs.google.com/document/d/1tSxfUIn-Ro6Pr1X4y21BbYKdsiK-nlWW3pGDfyh7SQ8/edit) for help with GitHub and GitHub Classroom. Once you have the URL of your personal GitHub repository, open the IntelliJ terminal. Move into the **`src/`** folder, then use the command **`git clone <URL>`**
Once you’ve cloned your personal repository from GitHub, you’ll need to rename the folder from **`lab4-<yourGitHubLogin>`** to just **`lab4`**. To do this, right click on the folder, then go to *Refactor*, *Rename*. You will have issues running your code until you make the change.
### Step 0: Reconfiguring IntelliJ
Isn’t it annoying when you have to type out a long variable name over and over again? Do you sit up at night wishing there was some way to save you those few keystrokes? You’re in luck...... introducing code completion!!!
IntelliJ has a nice feature that will help autocomplete code you’re writing. Turn it on now:
Go to “*Settings*” (or “*Preferences*” on older versions of IntelliJ) > *Search* for “code completion” > check “*Show suggestions as you type*” > press “*Apply*” then “*OK*”.
* If you’re having trouble enabling **code completion**, you might already have it turned on!
**Note**: Enabling code completion is *essential*. It will make your life a lot easier. Please call a TA over if you have any trouble with this step.
### Step 1: Building the GUI
First, you’ll be building the Graphical User Interface (GUI) pictured above from scratch!
The **`App`** class will be the top-level class for your whole program. Its job is to set up the outermost graphical container (a **`Stage`**).
:::info
**TODO**: In the **`start(...)`** method, set a title for your **`Stage`**—passed in as a parameter to the method—by using the **`Stage`** class’ **`setTitle(String s)`** method.
:::
:::info
**TODO**: Try running the program (**NEW**: You can run your code by opening **`App.java`** in the lab4 part of the Package Explorer and clicking the green right-facing arrow next to the App class definition. If it doesn’t work with the play button, ask a TA for help **now** so you can make it work before going off on your own!)
:::

You’ll probably notice that your **`Stage`** does not appear. It turns out that a **`Stage`** won’t show up unless it’s told to be shown. Call the **`show()`** method on your **`Stage`** to ensure it shows up.
:::info
**TODO**: Call the **`show()`** method on your **`Stage`** to ensure it shows up.
:::
:::info
**TODO**: Run the program again (You can re-run the last application you ran by clicking the green play button – or it might look like a curved arrow – at the top of the screen). You should see a small **`Stage`** pop up in the top-left corner of your screen with a gray background. You can resize the **`Stage`** by clicking and dragging its bottom-right corner.
:::
### Step 2: Adding Panes
Next, we want to add some **`Panes`** to our **`Stage`**: one in the center containing the rectangle, one on the bottom with a label, and one of the left containing a quit button. These three **`Panes`** should be contained in a root [**BorderPane**](https://docs.oracle.com/javafx/2/api/javafx/scene/layout/BorderPane.html), (a fourth, distinct **`Pane`** in our program), which is the top-level organizational section we want our **`Stage`** to display. We will eventually add the **`BorderPane`** to our **`Stage`** by passing it into the **`Scene`** in our **`App`** class.
First, let's make the **`BorderPane`** in **`PaneOrganizer`** so that we can keep track of the two **`Panes`**. A **`BorderPane`** is a JavaFX organizational class that allows you to easily lay out certain objects on the left, right, top, bottom, and center of your application (see the graphic below).
<img style="display: block; margin: auto;" src="https://hackmd.io/_uploads/SJXUnUf2R.png" alt="JavaFX Image">
:::info
**TODO**: Create an instance variable “root” of type **`BorderPane`** in your **`PaneOrganizer`** class. Don’t forget to initialize it in the constructor.
* You need to import the **`BorderPane`** class in order to use it. Sometimes IntelliJ will do this for us. If not, “BorderPane” will show up in red and you can hover your mouse over it to easily import in the class.
:::
:::info
**TODO**: Check that the proper **`BorderPane`** class has been properly imported. Near the top of your file you should see the line:
import javafx.scene.layout.BorderPane;
If it is not there, please make sure to add this in.
:::
:::danger
**Note**: Throughout the course of this lab and in CS15 generally, you may have to import other classes. IntelliJ might give you multiple import options (it often defaults to "java.awt"), but you should **always** choose the import statement that contains “javafx”.
:::
:::info
**TODO**: Now write an accessor method with the signature **`public BorderPane getRoot()`** that returns the **`BorderPane`** we just created so that we can eventually add it to our Stage.
:::
Now, we can add the **`BorderPane`** to our **`Stage`**. To do this, we will create a **`Scene`**. You can think of a [Scene](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/Scene.html) as being a container for all GUI items. In CS15, you'll only need one **`Scene`** per application.
:::info
**TODO**: Go back to the file **`App.java`**. In the **`start()`** method, instantiate a **`PaneOrganizer`** and add the **`BorderPane`** you have just created to a new **`Scene`** by calling:
PaneOrganizer organizer = new PaneOrganizer();
Scene scene = new Scene(organizer.getRoot(), Constants.SCENE_WIDTH, Constants.SCENE_HEIGHT);
stage.setScene(scene);
:::
**TIP**: Throughout the course of this lab, we will be giving you lines of code to use in your project. Try rewriting the code rather than copying it from the handout to avoid errors.
**Note**: since the **`Stage`** is an object, its properties constantly update, which means you can call **`stage.show()`** before calling **`setScene()`**, and it would display the correct **`Scene`**. However, we prefer to call **`stage.show()`** at the end to make the code more logical and easier to understand.
### Are you there pane?
If you run the program now and expand the **`Stage`**, it looks like nothing has changed. How do we know that our **`BorderPane`** is even there? Let’s make sure everything’s working by giving our **`BorderPane`** a background color by calling the method **`setStyle()`** on it.
**`Panes`** rely on [CSS](https://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html) for much of their styling. It’s slightly different from the JavaFX colors which we’ve used in the past, so we have set up some CSS colors in the constants class for you to use to color your panes.
:::info
**TODO**: Set the background color of your **`BorderPane`** to the correct color by calling **`setStyle(“-fx-background-color: #e4cbff”)`** on your root **`BorderPane`** in the **`PaneOrganizer`**'s constructor.
:::
Now, when you run the program and expand the **`Stage`** by clicking and dragging, the window should be filled in purple. That means our **`BorderPane`** is displaying and everything is working properly so far.
If you’re not seeing purple, you’ve got some debugging to do – feel free to call over a TA if you’re stuck! The graphic should look as follows:
<img style="display: block; margin: auto;" src="https://hackmd.io/_uploads/HJIVfPfhR.png" alt="JavaFX Image">
### Step 3: Create and Sub-Size Panes
Now that we have a **`PaneOrganizer`** with a root **`BorderPane`**, we can add some of the panes that will be contained within the **`BorderPane`**. The **`BorderPane`** is how we will organize our GUI, but we still need to fill it in with the three **`Panes`** we discussed before: one contains the quit button, one contains the rectangles, and the final pane contains the label at the bottom of the app. Let’s first make the button **`Pane`**, which contains the quit button.
To add new **`Panes`** to our app, we will be making use of private methods.
Within your **`PaneOrganizer`** class, there should be a private method called **`createButtonPane()`** that creates an instance of the **`Pane`** class and styles it (gives the pane a size and color). This method should not return anything.
Note that we used a value from the **`Constants`** class for the size and color of **`buttonPane`** – the rest of the colors you will have to give your **`Panes`** can be found there to use.
:::info
**TODO**: Call this method in the constructor of **`PaneOrganizer`** and run your code.
:::
Note that nothing has changed in your GUI! Why hasn’t anything changed? Because the **`createButtonPane()`** method creates instances of the button pane and the button inside, but it never adds the pane to the **`BorderPane`**, or adds the button to the **`buttonPane`**.
:::info
**TODO**: Edit the **`createButtonPane`** method to add **`buttonPane`** to your root **`BorderPane`** by using its **`setLeft(...)`** method and passing in **`buttonPane`**.
:::
Run your program. You should now see the buttonPane show up!
<img style="display: block; margin: auto;" src="https://hackmd.io/_uploads/Sy_YcrXnA.png" alt="JavaFX Image">
:::info
**TODO**: Add the **`button`** to your **`buttonPane`** by calling **`buttonPane.getChildren().add(...)`** method and passing in the button.
:::
Run your program. You should now see the **`button`** show up within the **`buttonPane`**!
### Step 4: Setting up Button Action
In order for the button to work, we need to let the button know that it is expecting input from a user. We can do this by using a special method: **`setOnAction`**. You’ll notice that the **`setOnAction`** method is expecting an argument…. time for *lambda expressions*!
Any user input to a JavaFX program (e.g. clicking a button, pressing a key) produces an **`Event`**. **`Events`** have many different subclasses that can be used more specifically in different situations. For buttons, a click will spawn an **`ActionEvent`** – ++this is the *type* of the parameter you’ll use for your lambda expression++. You’ll see another type of **`Event`** when we move to key input.
In this case, we want our button to quit the program. Luckily for us, Java already has a method for this that we can use.
:::info
**TODO**: Tell your **`button`** it should be reacting to a click by calling the **`setOnAction`** method on it. Use **`(ActionEvent e)`** as the parameter type/name and **`System.exit(0)`** as the method body for your lambda expression within the buttons **`setOnAction`** method. Your full line of code to quit the program should look like this:
button.setOnAction((ActionEvent e) -> System.exit(0));
:::
Let’s break this line down. When the **`button`** is clicked, it produces an **`ActionEvent`**. This **`ActionEvent`** is passed into the lambda expression, which then executes its body, **`System.exit(0)`**.
But why do we even need to take in an **`ActionEvent`** if we never use it? Well, clicking a **`Button`** generates an **`ActionEvent`**, and Java requires that the lambda expression we provide takes in this **`ActionEvent`**, even if it does nothing with it. Passing in a lambda expression with no parameters or a different parameter list will result in an *incompatible* type error.
:::info
**TODO**: Run your program and try clicking on the button. Your program should quit!
:::
### Step 5: Creating and Adding Contents to the Bottom Pane
At this point, we've created a **`BorderPane`** root that contains a **`buttonPane`** as its left node. Now, let’s add another **`Pane`** to our GUI to hold the message found at the bottom of the screen. Let's create a **`labelPane`** with the label: “Hi, I’m a label.”
:::info
**TODO**: Write a ++private++ method called **`createLabelPane()`** in the **`PaneOrganizer`** class and call it in the **`PaneOrganizer`** constructor.
:::
:::info
**TODO**: In **`createLabelPane()`**, declare and instantiate **`labelPane`** as an [HBox](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/HBox.html) – a special type of **`Pane`** that has horizontal layout capabilities. Use the appropriate values from the constants class to size and color your labelPane. (Hint: this will look very similar to how you did it in **`createButtonPane()`** – just be sure to use the correct **`Constants`**!)
:::
:::info
**TODO**: In **`createLabelPane()`**, declare and instantiate a [Label](https://docs.oracle.com/javafx/2/api/javafx/scene/control/Label.html). Pass in a string as an argument in the **`Label`**’s constructor (this string will become the text of the label). Then add it to the **`labelPane`**’s list of children.
:::
:::info
**TODO**: Add **`labelPane`** to the **`BorderPane`** using **`setBottom()`** and passing in your instance of **`labelPane`**.
:::
:::info
**TODO**: Call the **`setAlignment(...)`** method on **`labelPane`** and pass [Pos.CENTER](https://docs.oracle.com/javafx/2/api/javafx/geometry/Pos.html) in as a parameter to center the label.
:::
:::info
**TODO**: Run your program. The label should show up! Your GUI should look like this:
:::
<img style="display: block; margin: auto;" src="https://hackmd.io/_uploads/BJKkeLmn0.png" alt="JavaFX Image">
:::success
**Checkpoint 1**: Look through the code you have written so far and make sure you understand what is happening. Having a thorough understanding of using JavaFX is important for future projects, so call over a TA if you have any questions!
:::
### Step 6: Adding Rectangles
Now that we have Panes for our **`Button`** and **`Label`**, let’s create the center pane we will use to contain the rectangles. We will do this all within a **`createRectsPane()`** helper method.
:::info
**TODO**: Write another ++private++ method within the **`PaneOrganizer`** called **`createRectsPane()`**
:::
:::info
**TODO**: At the beginning of this method, create a new **`Pane`**(call it **`rectsPane`**). Use the appropriate width, height, and color constants for **`rectsPane`** to **`setPrefSize`** and **`setStyle`** of your new **`Pane`**.
:::
:::info
**TODO**: Add **`rectsPane`** to your **`BorderPane`** by using the **`setCenter(...)`** method and passing in **`rectsPane`**.
:::
:::info
**TODO**: In the constructor for your **`PaneOrganizer`** class, after instantiating your **`BorderPane`**, call your **`createRectsPane()`** method.
:::
:::info
**TODO**: Run your program. You should now see the **`buttonPane`**, **`labelPane`**, and the **`rectsPane`** in the GUI window! (you should no longer see the purple color of the **`BorderPane`** because the three new panes fill the whole **`BorderPane`** container)
:::
Now that we know our center **`Pane`** has been added, let’s add a **`Rectangle`** to it.
Go to the final class, **`MyRectangle`**, which we already created for you with some stencil code included. The purpose of this class is to create a **`Rectangle`** shape with the capability to move in response to a keyboard entry. This is called a “++wrapper class++”. A wrapper class is any class which "wraps" or "encapsulates" the functionality of another class or component. In this case, we are “wrapping,” or including, a standard JavaFX **`Rectangle`**, and we are adding our own functionality of certain methods that will move the rectangle left and right. In a sense, we will create a **`Rectangle`** inside our **`MyRectangle`** class, and we will redefine it according to the needs of our program. This concept of a “wrapper class” will be useful in many future projects.
#### Overarching Design
The only thing we can add to a **`Pane`** is a **`Node`**, so to add a **`MyRectangle`**, we actually will be adding the instance of **`Rectangle`** that graphically represents a **`MyRectangle`**. To do so, we will pass in the Pane where we want our **`MyRectangle`** to live into the constructor of the **`MyRectangle`** class. This way, **`MyRectangle`** can add its instance of **`Rectangle`** to the **`Pane`** while still keeping that **`Node`** externally hidden!
In other words, to add a **`MyRectangle`** to its **`Pane`**, the **`PaneOrganizer`** will pass the **`Pane`** to a **`MyRectangle`**, which can then add its **`Node`** to it.
#### Now let’s code this design out:
In the **`MyRectangle`** class, you’ll notice an instance variable **`rect`** of type **`Rectangle`**.
:::info
**TODO**: Make sure to instantiate **`rect`** in the constructor.
:::
Since **`MyRectangles`** can have different locations and colors, we can specify the location and color as arguments in the **`MyRectangle`** constructor!
:::info
**TODO**: Modify the **`MyRectangle`** constructor’s parameters so that it takes in a **`double`** for the x location, a **`double`** for the y location, and a [Color](https://docs.oracle.com/javafx/2/api/javafx/scene/paint/Color.html).
**Note**: this color is a JavaFX class [Color](https://docs.oracle.com/javafx/2/api/javafx/scene/paint/Color.html), which is different from the CSS color (declared via string) used earlier.
:::
Since we want all of our **`MyRectangles`** to be the same size in this lab, we don’t need to have parameters to specify size. Instead, we can automatically set the size in the **`MyRectangle`** constructor to the constant size we want.
:::info
**TODO**: Set the size, location, and color of your **`Rectangle`**, using constants and the values passed in from the constructor. Take note of the different ways to *instantiate* your rectangle…
**Note**: There are many different constructors listed in the shape documentation (shown in the picture below). Some of the constructors take in parameters and they can be useful to set the size, location, and color of your rectangle. Unfortunately, no constructor exists that takes in all five parameters at once, so you’ll have to use setter methods to set the rectangle’s traits for the remaining parameters.
:::
<img style="display: block; margin: auto;" src="https://hackmd.io/_uploads/H16lSLXn0.png" alt="JavaFX Image">
For additional information about how to accomplish this refer to the [Graphics II](https://cs.brown.edu/courses/cs015/lecture/pdf/CS15.Lecture_10_Graphics_Part_II.10.8.24.pdf) lecture or [JavaFX Shape Documentation](https://docs.google.com/document/d/1cOq649OLNp0-UHxz5W5KAOH-KyM2VXvq_TKmuGHv0Rg/edit)! (If looking at the Java Shape Documentation, look under javafx.scene.shape.Shape for information on setting the color).
Now that we’ve made good progress on the *wrapper class*, it’s time to go back to the **`createRectsPane()`** method in the **`PaneOrganizer`** class.
:::info
**TODO**: Create a local variable of type **`MyRectangle`** in **`createRectsPane`** and call it **`stationaryRect`**. Make sure to input the correct parameters in the **`MyRectangle`** constructor using values found in the **`Constants`** class (ex. **`Constants.STATIONARY_RECT_XLOC, Constants.STATIONARY_RECT_COLOR`**)
:::
If you run your program now, you will not see your **`MyRectangle`**. This is because it has not yet been added to **`rectsPane`** as a child.
:::info
**TODO**: Modify the **`MyRectangle`** constructor again so that it takes in a **`Pane`** in addition to the other parameters. Then, at the bottom of your constructor add the **`Rectangle`** as a child by calling the line below:
myPane.getChildren().add(this.rect);
:::
:::info
**TODO**: Go back to **`createRectsPane`** in **`PaneOrganizer`** and add your **`rectsPane`** as an argument to instantiate your **`MyRectangle`**, **`stationaryRect`**.
:::
Try running your application again - this time, the **`Rectangle`** should show up!
<img style="display: block; margin: auto;" src="https://hackmd.io/_uploads/rkpkDLQnR.png" alt="JavaFX Image">
Now let’s create another rectangle, but this one will be the moving rectangle. In order to move the rectangle we will need to have access to the rectangle throughout the **`PaneOrganizer`** class.
:::info
**TODO**: Declare a private instance variable called **`movingRect`**.
:::
:::info
**TODO**: Instantiate the **`movingRect`** variable within the **`createRectsPane()`** method. Make sure to pass the correct arguments into the **`MyRectangle`** constructor using values found in the **`Constants`** class.
:::
Your GUI should now look like the image at the start of the lab!
:::success
**Checkpoint 2**: Call a TA over to check your program!
:::
# Part 2: Responding to User Input
### Step 7: Adding an EventHandler for Key Input
Now it’s time to make our application respond to key input by the user. Keyboard input to a program generates a special type of JavaFX **`Event`** known as a **`KeyEvent`** (remember that clicking a button generates an **`ActionEvent`**).
Notice in the stencil code you are given the following method:
private void handleKeyPress(KeyEvent e) {…}
In this method, the **`keyPressed`** variable stores what key was pressed. If that key is the spacebar, “Spacebar!” will print in the terminal. Since this is a *helper method* that is specific to the **`PaneOrganizer`**, it has private visibility.
Let’s now use a *lambda expression* to call the **`handleKeyPress`** method whenever keyboard input is detected.
Note that a Key **`EventHandler`** needs to be added to a JavaFX **`Pane`**, or else it will not register the key input. We will need to set the focus of this user input on the specific **`Pane`**. This is because any graphical element that can be affected by user input needs to belong to a “traversable cycle,” meaning that every JavaFX object should check when a user enters input. JavaFX will not know that the key input should target a **`Pane`** until it’s added to this cycle by setting the focus on it.
In this case, we want to add the **`KeyHandler`** to the **`Pane`** containing all of the **`MyRectangles`**, i.e. the **`rectsPane`**, so that our moving rectangle will be responsive to the key input.
Now let’s add the **`KeyHandler`** to **`rectsPane`**:
:::info
**TODO**: Use the **`setOnKeyPressed`** method to add the Key **`EventHandler`** to **`rectsPane`** at the bottom of **`createRectsPane()`**. The parameter type of this lambda expression should be a **`KeyEvent`** and it should call the **`handleKeyPress`** method:
:::
:::info
**TODO**: Try running your program now and pressing different keys. Notice that your application only responds to the spacebar being pressed, and that exits the program! That’s not what we want to happen!
:::
Notice that your button has a blue outline. This is an indicator that the button currently holds the *focus* of the program, so hitting the spacebar will activate the button.
#### Focus? What’s that?
Focus refers to which JavaFX **`Node`** has the ability to respond to keyboard input, or which **`Node`** keyboard input is directed to. When we want a particular **`Node`** to be able to respond to keyboard input, we need to **`setFocusTraversable(true)`** on that **`Node`**. When we want a particular **`Node`** to be unable to respond to keyboard input, we must **`setFocusTraversable(false)`** on that one.
:::info
**TODO**: Go to the **`createButtonPane()`** method and set the proper focus on your **`button`** and **`buttonPane`** by adding the following lines of code:
buttonPane.setFocusTraversable(false);
button.setFocusTraversable(false);
:::
:::info
**TODO**: Now, let’s set the proper focus on your **`rectsPane`** by adding the line below right after adding the **`EventHandler`** in **`createRectsPane()`**:
rectsPane.setFocusTraversable(true);
:::
Now run the app. If your **`EventHandlers`** are set up correctly, then every time you press the spacebar, you should see “Spacebar!” printed out to the console.
Finally, note that we have called **`e.consume()`** at the end of the handleKeyPress method to prevent the event from “traveling” up the scene graph.
:::success
**Checkpoint 3**: Take a moment to look over your program and make sure you understand the changes you just implemented.
:::
### Step 8: Customizing your EventHandler
Next, we’re going to modify the **`KeyHandler`** so that instead of printing out “Spacebar!”, it controls the movement of one of the rectangles.
:::info
**TODO**: Fill in the method called **`moveRight()`** in your **`MyRectangle`** class to move the **`Rectangle`** right. You will need to set the new position of the **`Rectangle`** using the old position and an offset (provided in the constants class). Use the **`moveLeft()`** method as a guide.
:::
Right now, **`handleKeyPress`** just prints a message to the console. Let’s give it some more meaningful functionality: moving an instance of **`MyRectangle`**. To determine the direction we should move our **`MyRectangle`**, we can refer to the key stored in the **`keyPressed`** variable.
:::info
**TODO**: Implement a **`switch`** based on the **`keyPressed`** variable in the **`handleKeyPress()`** method. The **`switch`** should have 2 cases: one each for the LEFT and RIGHT arrow keys on the keyboard, which dictates movement left and right, respectively.
* For the LEFT case, call your **`moveLeft()`** method on **`movingRect`**.
* For the RIGHT case, call your **`moveRight()`** method on **`movingRect`**.
* Make sure to add a **`default`** case to your switch statement as well! In this case, since we don’t want the **`default`** case to do anything, it can consist of just a **`break`** statement
:::
Run your program and check that everything is working correctly! The black rectangle should be able to overlap the red rectangle.
<img style="display: block; margin: auto;" src="https://hackmd.io/_uploads/S1H4CIQh0.png" alt="JavaFX Image">
#### A Note On Variables
Go back to your **`createRectsPane`** method. Notice how the **`stationaryRect`** local variable appears in gray? That’s because it is never used after initialization – no methods are ever called on it! This makes **`stationaryRect`** a great example of an *unnecessary* local variable. Unnecessary variables take up space in memory that can be better allocated elsewhere, so we want to remove them from our programs wherever possible.
:::info
**TODO**: Delete the **`stationaryRect`** variable in **`createRectsPane`** to free up that space in memory. The line of code instantiating the red **`MyRectangle`** should now start with the new keyword.
:::
:::success
**Checkpoint 4**: Call over a TA once your unnecessary variable is removed and everything is working in order to get checked off!
:::