Java FX – GUIs
TOPIC 02 – HANDLING EVENTS
LESSON NOTE
EVENTS
In
computer science, an event occurs when a control is triggered in some way. The most common example, is when a button
is clicked. Another example would be
when the <Enter> key is hit inside of a TextField.
RESONPONDING TO EVENTS
Computer
programs often need to respond to an event when they occur. This is called event driven
programming. In this lesson, we will
learn how to make Java respond to events.
EVENT HANDLER
An
event handler is an object that takes care of responding to an event. For example, when a button is clicked, the
event handler is responsible for the response. Essentially, the event handler contains a
method in it that gets executed each time an event occurs.
THE HANDLE METHOD
For
Java FX, our event handler class needs to implement the EventHandler
interface. This forces our class to
have the following method in it:
public void handle(ActionEvent e)
It is inside this method that we will write the code to respond to the
event. For example, if the event was a
button click, perhaps we would make some text appear in a text field, or
perhaps we would open or close a window.
ALL
IN ONE CLASS
We can make a separate class from our Application class deal with
handling events. However, this has one
big disadvantage: That class doesn't have access to the data fields of our
Application class. So we would have to
find a way to communicate between the two classes. That is certainly possible, but at least
for now, it's easier to place the handle method inside the same class as our
Application class.
So this gives us the setup below.
Our class extends Application and implements EventHandler. The events it deals with are ActionEvent objects so we specify that. That class contains both the start and the
handle methods. Note that the setup
below doesn't show the main method that might be required depending on your
IDE.
public class FirstApplication extends Application implements EventHandler<ActionEvent>
{
public void
start(Stage primaryStage) throws Exception
{
//Create the GUI look here
}
public void handle(ActionEvent e)
{
//Handle events here
}
}
|
CONTROLS
AS DATA FIELDS
In order the code in the handle method to have access to the controls
in the start method, we need to make the controls datafields. We simply declare each control above the
start method and create each inside start.
EXAMPLE
1 – CONSOLE HELLO
The following window includes the handle method that is executed
when the button is clicked. The
method simply displays "Hello there." in the console.
NEW CODE EXPLANATION
The class now implements
the EventHandler interface for ActionEvents. So we add the following to the end of the
class declaration:
implements EventHandler<ActionEvent>
Doing the above forces
us to include the handle method.
Inside that method, we will simply output a message to the console.
public void handle(ActionEvent e)
{
System.out.println("Hello
there.");
}
Before we can make this
work though, we have to specify that this class will listen for events
related to the button. So, inside
the start method, we need the line:
b1.setOnAction(this);
Also, notice that the
Button control is declared as a datafield.
While doing so isn't important in this example, it will be necessary
in all future ones. We will declare
all controls as datafields to the class in order to make them accessible to
the handle method.
FULL CODE
Below is the full code
excluding the import statements. The
code with the new concepts is highlighted in yellow.
public class FirstApplication extends Application implements
EventHandler<ActionEvent>
{
public
Button b1;
@Override
public void start(Stage primaryStage)
throws Exception
{
//CREATE CONTROLS
b1 = new
Button();
b1.setText("Say Hi");
b1.setOnAction(this); //specify handler object
//CREATE LAYOUT & ADD CONTROLS
FlowPane layout = new FlowPane();
layout.getChildren().add(b1);
//CREATE SCENE AND ADD IT TO STAGE
Scene
s = new Scene(layout, 200, 100);
primaryStage.setScene(s);
//CONFIGURE & SHOW STAGE
primaryStage.setTitle("Console Hello");
primaryStage.show();
}
public static void main(String[] args)
{
Application.launch(args);
}
@Override
public
void handle(ActionEvent
e)
{
System.out.println("Hello
there.");
}
}
|
|
PLACING
OUTPUT IN A TEXTFIELD
When we create a GUI application, we don't actually want to use the
console anymore. We want to output to
be placed inside the window itself. One option is to place it inside a textfield object.
EXAMPLE
2 – OUTPUT TO TEXTFIELD
The following window has a button that generates a random number and
places it into the textfield.
NEW CODE EXPLANATION –
CREATING TEXTFIELD
This program is quite
similar to the previous one. We have
a TextField control that is a datafield.
It is constructed and added to the layout inside the start method.
NEW CODE EXPLANATION –
RESPONDING TO TEXTFIELD
In the handle method, we
generate a random number and place that number in the textfield using the
setText method.
FULL CODE
Below is the full code
excluding the import statements. The
code with the new concepts is highlighted in yellow.
public class FirstApplication extends Application implements EventHandler<ActionEvent>
{
public Button b1;
public
TextField t1;
@Override
public void start(Stage primaryStage)
throws Exception
{
//CREATE CONTROLS
b1 = new
Button();
b1.setText("Generate Number");
b1.setOnAction(this); //specify
handler object
t1
= new TextField();
//CREATE LAYOUT & ADD CONTROLS
FlowPane layout = new FlowPane();
layout.getChildren().add(b1);
layout.getChildren().add(t1);
//CREATE SCENE AND ADD IT TO STAGE
Scene
s = new Scene(layout, 250, 70);
primaryStage.setScene(s);
//CONFIGURE & SHOW STAGE
primaryStage.setTitle("TextField Number");
primaryStage.show();
}
public static void main(String[] args)
{
Application.launch(args);
}
@Override
public void handle(ActionEvent
e)
{
String msg
= ""+Math.random();
t1.setText(msg);
}
}
|
|
SOURCE
OF EVENT
Most applications have more than one control that can create
events. We can tell which control
triggered the event by making use of the ActionEvent
object passed to the handle method.
EXAMPLE
3 – TWO BUTTONS
The window application below has two buttons that generate an
event. We see how to respond to each
but differently.
NEW
CODE EXPLANATION
We add a button to the window.
We also add a listener to the button.
In the handle event, we differentiate between an event triggered by
button #1 and #2 and place a corresponding message in the text field.
public void handle(ActionEvent e)
{
if (e.getSource() == b1)
{
t1.setText("Hi there!");
}
else if (e.getSource() == b2)
{
t1.setText("Hey there!");
}
}
FULL
CODE
Below is the full code
excluding the import statements. The
code with the new concepts is highlighted in yellow.
public class FirstApplication extends Application implements EventHandler<ActionEvent>
{
public Button b1;
public
Button b2;
public TextField t1;
@Override
public void start(Stage primaryStage)
throws Exception
{
//CREATE CONTROLS
b1 = new
Button();
b1.setText("Hi");
b1.setOnAction(this);
b2
= new Button();
b2.setText("Hey");
b2.setOnAction(this);
t1 = new TextField();
//CREATE LAYOUT & ADD CONTROLS
FlowPane layout = new FlowPane();
layout.getChildren().add(b1);
layout.getChildren().add(t1);
layout.getChildren().add(b2);
//CREATE SCENE AND ADD IT TO STAGE
Scene
s = new Scene(layout, 250, 70);
primaryStage.setScene(s);
//CONFIGURE &
SHOW STAGE
primaryStage.setTitle("Two Buttons");
primaryStage.show();
}
public static void main(String[] args)
{
Application.launch(args);
}
@Override
public
void handle(ActionEvent
e)
{
if
(e.getSource() == b1)
{
t1.setText("Hi
there!");
}
else
if (e.getSource()
== b2)
{
t1.setText("Hey
there!");
}
}
}
|
|
|