name: inverse layout: true class: taylor msoe --- class: center, middle .title[ # JavaFX ## Graphical User Interfaces ] ??? * **P** speaker view * **C** clone slideshow * **?** help --- # JavaFX as a Theater * Our Graphical User Interface can be thought of as a theater -- * **Stage** — The window where the action occurs -- * **Scene** — The visual content on the stage -- * **Actors/Props** — Our scene will have props and actors -- + Props just sit there, e.g., `Label`s, `ImageView`s, ... + Actors may respond to events within the scene, e.g., `Button`s, `TextField`s, ... -- * **Costumes/Makeup** — JavaFX uses Cascading Style Sheets to style our components -- * **Scripts** — Each actor may have a script. -- * **Director** — The main application logic is typically found in the `start()` method of the `Application` class which sets up the stage, scene, and actors -- * **Backstage Crew** — JavaFX uses background tasks (threads) to keep things running smoothly --- # `Application` Class * Create a JavaFX application by extending the [`Application`](https://javadoc.taylorial.com/javafx.graphics/application/Application.html) class -- * Implement the abstract `start()` method -- * A class **must** be declared abstract if it has one or more abstract methods -- * `start(Stage stage)` method is passed a reference to a [`Stage`](https://javadoc.taylorial.com/javafx.graphics/stage/Stage.html) object -- * The `Stage` represents the application window -- + `setScene(Scene scene)` - set the scene of the stage + `show()` - makes the window visible --- # Example .left-column[ ![Hello World](javafxa.png) ] .right-column[ ``` public class HelloWorld extends Application { @Override public void start(Stage stage) { Label label = new Label("Hello World!"); label.setFont(new Font(40)); Scene scene = new Scene(label); stage.setTitle("Welcome to JavaFX!"); stage.setScene(scene); stage.show(); } public static void main(String[] args) { Application.launch(args); } } ``` ] --- # `Scene` Class * The [`Scene`](https://javadoc.taylorial.com/javafx.graphics/scene/Scene.html) class is the container for the scene graph -- * Must set a root [`Parent`](https://javadoc.taylorial.com/javafx.graphics/scene/Parent.html) -- + Could be a **leaf** node with no additional nodes -- - (e.g., a [`Label`](https://javadoc.taylorial.com/javafx.graphics/scene/control/Label.html), [`Button`](https://javadoc.taylorial.com/javafx.graphics/scene/control/Button.html), [`ScrollBar`](https://javadoc.taylorial.com/javafx.graphics/scene/control/ScrollBar.html), ...) -- + Could be a **branch** node with additional nodes -- - [`Group`](https://javadoc.taylorial.com/javafx.graphics/scene/Group.html) - contains a list of children -- - [`WebView`](https://javadoc.taylorial.com/javafx.web/scene/web/WebView.html) - manages a [`WebEngine`](https://javadoc.taylorial.com/javafx.web/scene/web/WebEngine.html) and displays its content -- - [`Pane`](https://javadoc.taylorial.com/javafx.graphics/scene/layout/Pane.html) - base class for layout panes - [`FlowPane`](https://javadoc.taylorial.com/javafx.graphics/scene/layout/FlowPane.html) - lays out its children in a flow that wraps at the flowpane's boundary --- # Adding to a Pane .pull-right[ ![Teenager](javafxb.png) ] ``` public class Teenager extends Application { private Label response; public static final int HEIGHT = 200; public static final int WIDTH = 300; @Override public void start(Stage stage) { response = new Label(); TextField input = new TextField(); Button clear = new Button("Clear"); Pane pane = new FlowPane(); * pane.getChildren().add(new Label("Please enter your age: ")); * pane.getChildren().add(input); * pane.getChildren().add(response); * pane.getChildren().add(clear); stage.setScene(new Scene(pane, WIDTH, HEIGHT)); stage.show(); } } ``` --- # Setting Actions ``` @Override public void start(Stage stage) { // ... // ... // ... pane.getChildren().add(clear); * input.setOnAction(this::enterPressed); * clear.setOnAction(this::clearPressed); stage.setScene(scene); stage.show(); } * private void clearPressed(ActionEvent actionEvent) { * response.setText(""); * } ``` --- # Setting Actions continued ``` private void enterPressed(ActionEvent actionEvent) { String text = ((TextField)actionEvent.getSource()).getText(); int age = Integer.parseInt(text); String not = ""; if(age<13 || age>19) { not = "not "; } response.setText("You are " + not + "a teenager."); } ``` --- # Alternative to `parseInt()` ``` private void enterPressedRobust(ActionEvent actionEvent) { String text = ((TextField)actionEvent.getSource()).getText(); Scanner parser = new Scanner(text); * if(parser.hasNextInt()) { * int age = parser.nextInt(); boolean isTeenager = age>12 && age<20; response.setText("You are " + (isTeenager ? "" : "not ") + "a teenager"); * } else { * response.setText("Please enter an integer"); * } } ```