From 345b4c8e1c190842bc21f63c7fb7fa57fd7a7d31 Mon Sep 17 00:00:00 2001 From: Ana Date: Wed, 13 Sep 2023 19:42:29 +0200 Subject: [PATCH 1/3] Add javafxdoc and links inside the articles --- app/data/javafxdoc.json | 58 +++++++++++++++++++ .../01_javafx/01_app_structure.md | 34 +++++------ .../01_javafx/02_layout_controls.md | 38 ++++++------ .../01_javafx/03_effects_gradients.md | 15 +++-- .../01_javafx/04_javafx_properties.md | 16 ++--- .../07_rich_client_apps/01_javafx/05_fxml.md | 28 ++++----- .../01_javafx/06_all_together.md | 56 +++++++++--------- gulpfile.js | 21 +++++++ 8 files changed, 172 insertions(+), 94 deletions(-) create mode 100644 app/data/javafxdoc.json diff --git a/app/data/javafxdoc.json b/app/data/javafxdoc.json new file mode 100644 index 0000000..2ffaf94 --- /dev/null +++ b/app/data/javafxdoc.json @@ -0,0 +1,58 @@ +{ + "current_release": "19", + + "javafx-documentation": "https://openjfx.io/javadoc/@@CURRENT_RELEASE@@/javafx.graphics/", + "javafxdoc_root": "https://openjfx.io/javadoc/@@CURRENT_RELEASE@@/javafx.graphics/", + + "Application": "javafx/application/Application.html", + + "Scene": "javafx/scene/Scene.html", + + "Stage": "javafx/stage/Stage.html", + + "Group": "javafx/scene/Group.html", + + "AnchorPane": "javafx/scene/layout/AnchorPane.html", + "BorderPane": "javafx/scene/layout/BorderPane.html", + + "FlowPane": "javafx/scene/layout/FlowPane.html", + "GridPane": "javafx/scene/layout/GridPane.html", + "HBox": "javafx/scene/layout/HBox.html", + "StackPane": "javafx/scene/layout/StackPane.html", + "VBox": "javafx/scene/layout/VBox.html", + + "ImageView": "javafx/scene/image/ImageView.html", + + "Color": "javafx/scene/paint/Color.html", + "LinearGradient": "javafx/scene/paint/LinearGradient.html", + + "Ellipse": "javafx/scene/shape/Ellipse.html", + "Line": "javafx/scene/shape/Line.html", + "Path": "javafx/scene/shape/Path.html", + "Rectangle": "javafx/scene/shape/Rectangle.html", + "Shape": "javafx/scene/shape/Shape.html", + "Text": "javafx/scene/shape/Text.html", + + + "Button": "javafx/scene/control/Button.html", + "ButtonBar": "javafx/scene/control/ButtonBar.html", + "ListView": "javafx/scene/control/ListView.html", + "SplitPane": "javafx/scene/control/SplitPane.html", + "TextField": "javafx/scene/control/TextField.html", + "TextArea": "javafx/scene/control/TextArea.html", + + "Animation.Status": "javafx/animation/Animation.Status.html", + "RotateTransition": "javafx/animation/RotateTransition.html", + "ParallelTransition": "javafx/animation/ParallelTransition.html", + "PauseTransition": "javafx/animation/PauseTransition.html", + "SequentialTransition": "javafx/animation/SequentialTransition.html", + "Transition": "javafx/animation/Transition.html", + + "When": "javafx/beans/binding/When.html", + + "FXMLLoader": "javafx/fxml/FXMLLoader.html", + "Initializable": "javafx/fxml/Initializable.html", + + "ObservableList": "javafx/collections/ObservableList.html", + "SortedList": "javafx/collections/transformation/SortedList.html", +} \ No newline at end of file diff --git a/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/01_app_structure.md b/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/01_app_structure.md index 965db2b..0793dfc 100644 --- a/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/01_app_structure.md +++ b/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/01_app_structure.md @@ -28,12 +28,12 @@ byline: 'and is from   ## JavaFX Is Single-Threaded -You must always construct and modify the `Stage` and its scene objects on the `JavaFX Application Thread`. Note that JavaFX (like `Swing`) is a single-threaded UI model. For the JavaFX developer, this is mostly a straightforward restriction. +You must always construct and modify the [`Stage`](javafxdoc:Stage) and its scene objects on the `JavaFX Application Thread`. Note that JavaFX (like `Swing`) is a single-threaded UI model. For the JavaFX developer, this is mostly a straightforward restriction. As you create UI elements, respond to event handlers, manage dynamic content with animation, or make changes in the scene graph, work continues to execute on the JavaFX Application Thread. To keep the UI responsive, however, you should assign long-running work to background tasks in separate threads. In this case, work that modifies the UI must be separate from work being executed on a background thread. @@ -41,7 +41,7 @@ Fortunately, JavaFX has a well-developed concurrency API that helps developers a   ## Hierarchical Node Structure -Continuing with the theater metaphor, the `Stage` holds a scene. The scene consists of JavaFX elements such as the root, which is the top scene element and contains what is called the scene graph. +Continuing with the theater metaphor, the [`Stage`](javafxdoc:Stage) holds a scene. The scene consists of JavaFX elements such as the root, which is the top scene element and contains what is called the scene graph. The scene graph is a strictly hierarchical structure of elements that visualize your application. These elements are called Nodes. A Node has exactly one parent (except the root node) and may contain other Nodes. Or, a Node can be a leaf node with no children. Nodes must be added to the scene graph in order to participate in the rendering of that scene. Furthermore, a Node may be added only once to a scene, unless it is first removed and then added somewhere else. @@ -54,10 +54,10 @@ as shown in the figure below. Coordinate values on the x-axis increase to the ri JavaFX also supports 3D graphics and represents the third dimension with z-axis values, providing depth. JavaFX has an absolute coordinate system, in addition to local coordinate systems that are relative to the parent. In each case, the coordinate system’s origin is the upper-left corner of the parent. In general, layout controls hide the complexities of component placement within the scene and manage the placement of its children for you. Component placement is based on the specific layout control and how you configure it. -It’s also possible to nest layout controls. For example, you can place multiple VBox controls in an `HBox` or put an `AnchorPane` into one pane of a `SplitPane` control. Other parent nodes are more complex visual nodes, such as `TextField`, `TextArea`, and `Button`. -These nodes have managed subparts. For example, `Button` includes a labeled text part and optional graphic. This graphic can be any node type but is typically an image or icon. +It’s also possible to nest layout controls. For example, you can place multiple VBox controls in an [`HBox`](javafxdoc:HBox) or put an [`AnchorPane`](javafxdoc:AnchorPane) into one pane of a [`SplitPane`](javafxdoc:SplitPane) control. Other parent nodes are more complex visual nodes, such as [`TextField`](javafxdoc:TextField), [`TextArea`](javafxdoc:TextArea), and [`Button`](javafxdoc:Button). +These nodes have managed subparts. For example, [`Button`](javafxdoc:Button) includes a labeled text part and optional graphic. This graphic can be any node type but is typically an image or icon. -Recall that leaf nodes have no child nodes. Examples include `Shape` (such as `Rectangle`, `Ellipse`, `Line`, `Path`, and `Text`) and `ImageView`, a node for rendering an image. +Recall that leaf nodes have no child nodes. Examples include [`Shape`](javafxdoc:Shape) (such as [`Rectangle`](javafxdoc:Rectangle), [`Ellipse`](javafxdoc:Ellipse), [`Line`](javafxdoc:Line), [`Path`](javafxdoc:Path), and [`Text`](javafxdoc:Text)) and [`ImageView`](javafxdoc:ImageView), a node for rendering an image. Just a word of warning: you should be using a plain text editor to create and save this file. Using a word processor will not work.   @@ -68,7 +68,7 @@ When you resize the window, the visible elements will remain centered in the res [![MyShapes application](/assets/images/javafx/myshapes-application.png)](/assets/images/javafx/myshapes-application.png) -The source code for this application is in the `MyShapes` program. Class `MyShapes` is the main class and extends `Application`. The JavaFX runtime system instantiates `MyShapes` as well as the primary Stage, which it passes to the overridden `start()` method. The runtime system invokes the `start()` method for you. +The source code for this application is in the `MyShapes` program. Class `MyShapes` is the main class and extends [`Application`](javafxdoc:Application). The JavaFX runtime system instantiates `MyShapes` as well as the primary Stage, which it passes to the overridden `start()` method. The runtime system invokes the `start()` method for you. ```java package org.modernclient; @@ -110,14 +110,14 @@ Note the import statements that reference packages in `javafx.application`, `jav --- -This program creates several nodes and adds them to a `StackPane` layout container. The program also creates the scene, configures the stage, and shows the stage. Let’s look at these steps in detail. +This program creates several nodes and adds them to a [`StackPane`](javafxdoc:StackPane) layout container. The program also creates the scene, configures the stage, and shows the stage. Let’s look at these steps in detail. -First, we create an `Ellipse` shape, providing a width and height in pixels. Since `Ellipse` extends `Shape`, we can also configure any `Shape` property. This includes fill, which lets you specify an interior paint value. +First, we create an [`Ellipse`](javafxdoc:Ellipse) shape, providing a width and height in pixels. Since [`Ellipse`](javafxdoc:Ellipse) extends [`Shape`](javafxdoc:Shape), we can also configure any [`Shape`](javafxdoc:Shape) property. This includes fill, which lets you specify an interior paint value.   ## Color -A `Shape`’s fill property can be a JavaFX color, a linear gradient, a radial gradient, or an image. Let’s briefly discuss color. You can specify colors in JavaFX several ways. -Here, we set the `Ellipse` fill property to `Color.LIGHTBLUE`. +A [`Shape`](javafxdoc:Shape)’s fill property can be a JavaFX color, a linear gradient, a radial gradient, or an image. Let’s briefly discuss color. You can specify colors in JavaFX several ways. +Here, we set the [`Ellipse`](javafxdoc:Ellipse) fill property to `Color.LIGHTBLUE`. ```java // Create an Ellipse and set fill color @@ -125,9 +125,9 @@ Ellipse ellipse = new Ellipse(110, 70); ellipse.setFill(Color.LIGHTBLUE); ``` -There are currently 147 predefined colors in the JavaFX Color class, named alphabetically from `ALICEBLUE` to `YELLOWGREEN`. However, you can also specify `Color` using web RGB values with either hexadecimal notation or decimal numbers. +There are currently 147 predefined colors in the JavaFX Color class, named alphabetically from `ALICEBLUE` to `YELLOWGREEN`. However, you can also specify [`Color`](javafxdoc:Color) using web RGB values with either hexadecimal notation or decimal numbers. You can optionally provide an alpha value for transparency. Fully opaque is 1 and fully transparent is 0. A transparency of .5, for example, shows the color but lets the background color show through as well. -Here are a few examples that set a shape’s fill with `Color`: +Here are a few examples that set a shape’s fill with [`Color`](javafxdoc:Color): ```java ellipse.setFill(Color.LIGHTBLUE); // Light blue, fully opaque @@ -143,7 +143,7 @@ Notably, you can interpolate a color’s values, and that is how JavaFX construc   ## Text -We next create a Text object. Text is also a `Shape` with additional properties, such as font, text alignment, text, and wrapping width. The constructor provides the text and the `setFont()` method sets its font. +We next create a Text object. Text is also a [`Shape`](javafxdoc:Shape) with additional properties, such as font, text alignment, text, and wrapping width. The constructor provides the text and the `setFont()` method sets its font. ```java // Create a Text shape with font and size @@ -156,12 +156,12 @@ text.setFont(new Font("Arial Bold", 24)); Note that we created the ellipse and text nodes, but they are not yet in our scene graph. Before we add them to the scene, we must put these nodes in some kind of layout container. Layout controls are extremely important in managing your scene graph. These controls not only arrange components for you but also respond to events such as resizing, the addition or removal of elements, and any changes to the sizes of one or more nodes in the scene graph. -To show you just how important layout controls are, let’s replace the `StackPane` from the original example with a `Group` and specify the placement manually. -`Group` is a parent node that manages its children but does not provide any layout capability. Here we create a group and add the ellipse and text elements with the constructor. We then specify group as the scene’s root node: +To show you just how important layout controls are, let’s replace the [`StackPane`](javafxdoc:StackPane) from the original example with a [`Group`](javafxdoc:Group) and specify the placement manually. +[`Group`](javafxdoc:Group) is a parent node that manages its children but does not provide any layout capability. Here we create a group and add the ellipse and text elements with the constructor. We then specify group as the scene’s root node: ```java Group group = new Group(ellipse, text); -. . . +... Scene scene = new Scene(group, 350, 230, Color.LIGHTYELLOW); ``` diff --git a/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/02_layout_controls.md b/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/02_layout_controls.md index e8ce486..451c74c 100644 --- a/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/02_layout_controls.md +++ b/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/02_layout_controls.md @@ -34,9 +34,9 @@ Let’s look at a few commonly used layout controls now to show you how JavaFX c   ## StackPane -A convenient and easy layout container is `StackPane`. This layout control stacks its children from back to front in the order that you add nodes. Note that we add the ellipse first so that it appears behind the text node. In the opposite order, the ellipse would obscure the text element. +A convenient and easy layout container is [`StackPane`](javafxdoc:StackPane). This layout control stacks its children from back to front in the order that you add nodes. Note that we add the ellipse first so that it appears behind the text node. In the opposite order, the ellipse would obscure the text element. -By default, `StackPane` centers all of its children. You can provide a different alignment for the children or apply an alignment to a specific node in the `StackPane`. For example, +By default, [`StackPane`](javafxdoc:StackPane) centers all of its children. You can provide a different alignment for the children or apply an alignment to a specific node in the [`StackPane`](javafxdoc:StackPane). For example, ```java // align the text only @@ -54,7 +54,7 @@ Although both the ellipse and the text appear at the bottom of the window, they   ## AnchorPane -`AnchorPane` manages its children according to configured anchor points, even when a container resizes. You specify an offset from the pane’s edge for a component. Here, we add a Label to an AnchorPane and anchor it to the lower-left side of the pane with a 10-pixel offset: +[`AnchorPane`](javafxdoc:AnchorPane) manages its children according to configured anchor points, even when a container resizes. You specify an offset from the pane’s edge for a component. Here, we add a Label to an AnchorPane and anchor it to the lower-left side of the pane with a 10-pixel offset: ```java AnchorPane anchorPane = new AnchorPane(); Label label = new Label("My Label"); @@ -63,12 +63,12 @@ AnchorPane.setLeftAnchor(label, 10.0); AnchorPane.setBottomAnchor(label, 10.0); ``` -`AnchorPane` is typically used as a top-level layout manager for controlling margins, even when the window is resized. +[`AnchorPane`](javafxdoc:AnchorPane) is typically used as a top-level layout manager for controlling margins, even when the window is resized.   ## GridPane -`GridPane` lets you place child nodes in a flexibly sized two-dimensional grid. Components can span rows and/or columns, but the row size is consistent for all components in a given row. Similarly, the column’s width is consistent for a given column. -`GridPane` has specialized methods that add nodes to a particular cell designated by a column and row number. Optional arguments let you specify column and row span values. +[`GridPane`](javafxdoc:GridPane) lets you place child nodes in a flexibly sized two-dimensional grid. Components can span rows and/or columns, but the row size is consistent for all components in a given row. Similarly, the column’s width is consistent for a given column. +[`GridPane`](javafxdoc:GridPane) has specialized methods that add nodes to a particular cell designated by a column and row number. Optional arguments let you specify column and row span values. For example, the first label here is placed in the cell corresponding to column 0 and row 0. The second label goes into the cell corresponding to column 1 and row 0, and it spans two columns (the second and third columns). We must also provide a row span value (here it is set to 1): ```java @@ -77,22 +77,22 @@ gridPane.add(new Label("Label1"), 0, 0); gridPane.add(new Label("Label2 is very long"), 1, 0, 2, 1); ``` -`GridPane` is useful for laying out components in forms that accommodate columns or rows of various sizes. `GridPane` also allows nodes to span either multiple columns or rows. -We use `GridPane` in our master-detail UI example (see _Putting It All Together_ section of this series). +[`GridPane`](javafxdoc:GridPane) is useful for laying out components in forms that accommodate columns or rows of various sizes. [`GridPane`](javafxdoc:GridPane) also allows nodes to span either multiple columns or rows. +We use [`GridPane`](javafxdoc:GridPane) in our master-detail UI example (see _Putting It All Together_ section of this series).   ## FlowPane and TilePane -`FlowPane` manages its children in either a horizontal or vertical flow. The default orientation is horizontal. You can specify the flow direction with the constructor or use method `setOrientation()`. Here, we specify a vertical orientation with the constructor: +[`FlowPane`](javafxdoc:FlowPane) manages its children in either a horizontal or vertical flow. The default orientation is horizontal. You can specify the flow direction with the constructor or use method `setOrientation()`. Here, we specify a vertical orientation with the constructor: ```java FlowPane flowpane = new FlowPane(Orientation.VERTICAL); ``` -`FlowPane` wraps child nodes according to a configurable boundary. If you resize a pane that contains a `FlowPane`, the layout will adjust the flow as needed. The size of the cells depends on the size of the nodes, and it will not be a uniform grid unless all the nodes are the same size. This layout is convenient for nodes whose sizes can vary, such as `ImageView` nodes or shapes. `TilePane` is similar to `FlowPane`, except `TilePane` uses equal-sized cells. +[`FlowPane`](javafxdoc:FlowPane) wraps child nodes according to a configurable boundary. If you resize a pane that contains a [`FlowPane`](javafxdoc:FlowPane), the layout will adjust the flow as needed. The size of the cells depends on the size of the nodes, and it will not be a uniform grid unless all the nodes are the same size. This layout is convenient for nodes whose sizes can vary, such as `ImageView` nodes or shapes. `TilePane` is similar to [`FlowPane`](javafxdoc:FlowPane), except `TilePane` uses equal-sized cells.   ## BorderPane -`BorderPane` is convenient for desktop applications with discreet sections, including a top toolbar (Top), a bottom status bar (Bottom), a center work area (Center), and two side areas (Right and Left). -Any of the five sections can be empty. Here is an example of a `BorderPane` with a rectangle in the center and a label at the top: +[`BorderPane`](javafxdoc:BorderPane) is convenient for desktop applications with discreet sections, including a top toolbar (Top), a bottom status bar (Bottom), a center work area (Center), and two side areas (Right and Left). +Any of the five sections can be empty. Here is an example of a [`BorderPane`](javafxdoc:BorderPane) with a rectangle in the center and a label at the top: ```java BorderPane borderPane = new BorderPane(); @@ -104,17 +104,17 @@ borderPane.setCenter(rectangle); BorderPane.setAlignment(colorLabel, Pos.CENTER); BorderPane.setMargin(colorLabel, new Insets(20,10,5,10)); ``` -Note that `BorderPane` uses a center alignment by default for the center area and a left alignment for the top. To keep the top area label centered, we configure its alignment with `Pos.CENTER`. We also set margins around the label with BorderPane static method `setMargin()`. The `Insets` constructor takes four values corresponding to the top, right, bottom, and left edges. Similar alignment and margin configurations apply to other layout components, too. +Note that [`BorderPane`](javafxdoc:BorderPane) uses a center alignment by default for the center area and a left alignment for the top. To keep the top area label centered, we configure its alignment with `Pos.CENTER`. We also set margins around the label with BorderPane static method `setMargin()`. The `Insets` constructor takes four values corresponding to the top, right, bottom, and left edges. Similar alignment and margin configurations apply to other layout components, too.   ## SplitPane -`SplitPane` divides the layout space into multiple horizontally or vertically configured areas. The divider is movable, and you typically use other layout controls in each of `SplitPane`’s areas. -We use `SplitPane` in our master-detail UI example (checkout _Putting It All Together_ part of these series). +[`SplitPane`](javafxdoc:SplitPane) divides the layout space into multiple horizontally or vertically configured areas. The divider is movable, and you typically use other layout controls in each of [`SplitPane`](javafxdoc:SplitPane)’s areas. +We use [`SplitPane`](javafxdoc:SplitPane) in our master-detail UI example (checkout _Putting It All Together_ part of these series).   ## HBox, VBox, and ButtonBar -The `HBox` and `VBox` layout controls provide single horizontal or vertical placements for child nodes. You can nest `HBox` nodes inside a `VBox` for a grid-like effect or nest VBox nodes inside an HBox component. -`ButtonBar` is convenient for placing a row of buttons of equal size in a horizontal container. +The [`HBox`](javafxdoc:HBox) and [`VBox`](javafxdoc:VBox) layout controls provide single horizontal or vertical placements for child nodes. You can nest [`HBox`](javafxdoc:HBox) nodes inside a [`VBox`](javafxdoc:VBox) for a grid-like effect or nest `VBox` nodes inside an `HBox` component. +[`ButtonBar`](javafxdoc:ButtonBar) is convenient for placing a row of buttons of equal size in a horizontal container.   ## Make a Scene @@ -153,8 +153,8 @@ public class MyShapes extends Application { } ``` -First, we construct the `Scene` and provide `stackPane` as the root node. We then specify its width and height in pixels and supply an optional fill argument for the background (`Color.LIGHTYELLOW`). +First, we construct the [`Scene`](javafxdoc:Scene) and provide `stackPane` as the root node. We then specify its width and height in pixels and supply an optional fill argument for the background (`Color.LIGHTYELLOW`). What’s left is to configure the Stage. We provide a title, set the scene, and show the stage. The JavaFX runtime renders our scene. -Below is a hierarchical view of the scene graph for our `MyShapes` application. The root node is the `StackPane`, which contains its two child nodes, `Ellipse` and `Text`. +Below is a hierarchical view of the scene graph for our `MyShapes` application. The root node is the [`StackPane`](javafxdoc:StackPane), which contains its two child nodes, `Ellipse` and `Text`. [![MyShapes scene graph](/assets/images/javafx/myshapes-scene-graph.png)](/assets/images/javafx/myshapes-scene-graph.png) diff --git a/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/03_effects_gradients.md b/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/03_effects_gradients.md index 4eb3e9e..3077fd6 100644 --- a/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/03_effects_gradients.md +++ b/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/03_effects_gradients.md @@ -38,7 +38,7 @@ Stop[] stops = new Stop[] { new Stop(0, Color.DODGERBLUE), new Stop(1.0, Color.LIGHTGREEN)}; ``` -The `LinearGradient` constructor specifies the x-axis range followed by the y-axis range. The following linear gradient has a constant x-axis but varies its y-axis. This is called a vertical gradient. +The [`LinearGradient`](javafxdoc:LinearGradient) constructor specifies the x-axis range followed by the y-axis range. The following linear gradient has a constant x-axis but varies its y-axis. This is called a vertical gradient. ```java // startX=0, startY=0, endX=0, endY=1 @@ -87,8 +87,7 @@ Here’s the code to add an action event handler to the text node: ```java text.setOnMouseClicked(mouseEvent -> { -System.out.println(mouseEvent.getSource().getClass() -+ " clicked."); + System.out.println(mouseEvent.getSource().getClass() + " clicked."); }); ``` When the user clicks inside the text, the program displays the line `class javafx.scene.text.Text` clicked. @@ -104,13 +103,13 @@ Let’s do something a bit more exciting and apply an animation to the `MyShape` ## Animation JavaFX makes animation very easy when you use the built-in transition APIs. Each JavaFX Transition type controls one or more Node (or Shape) properties. For example, the `FadeTransition` controls a node’s opacity, varying the property over time. To fade something out gradually, you change its opacity from fully opaque (1) to completely transparent (0). The `TranslateTransition` moves a node by modifying its translateX and translateY properties (or translateZ if you’re working in 3D). -You can play multiple transitions in parallel with a `ParallelTransition` or sequentially with a `SequentialTransition`. To control timing between two sequential transitions, use `PauseTransition` or configure a delay before a transition begins with `Transition` method `setDelay()`. You can also define an action when a `Transition` completes using the `Transition` action event handler property `onFinished`. +You can play multiple transitions in parallel with a [`ParallelTransition`](javafxdoc:ParallelTransition) or sequentially with a [`SequentialTransition`](javafxdoc:SequentialTransition). To control timing between two sequential transitions, use [`PauseTransition`](javafxdoc:PauseTransition) or configure a delay before a transition begins with [`Transition`](javafxdoc:Transition) method `setDelay()`. You can also define an action when a [`Transition`](javafxdoc:Transition) completes using the [`Transition`](javafxdoc:Transition) action event handler property `onFinished`. -Transitions begin with method `play()` or `playFromStart()`. Method `play()` starts the transition at its current time; method `playFromStart()` always begins at time 0. Other methods include `stop()` and `pause()`. You can query a transition’s status with `getStatus()`, which returns one of the `Animation.Status` enum values: `RUNNING`, `PAUSED`, or `STOPPED`. +Transitions begin with method `play()` or `playFromStart()`. Method `play()` starts the transition at its current time; method `playFromStart()` always begins at time 0. Other methods include `stop()` and `pause()`. You can query a transition’s status with `getStatus()`, which returns one of the [`Animation.Status`](javafxdoc:Animation.Status) enum values: `RUNNING`, `PAUSED`, or `STOPPED`. All transitions support the common properties `duration, autoReverse, cycleCount, onFinished, currentTime`, and either node or shape (for Shape-specific transitions). -Let’s define a `RotateTransition` now for our `MyShapes` program. The rotation begins when a user clicks inside the window. +Let’s define a [`RotateTransition`](javafxdoc:RotateTransition) now for our `MyShapes` program. The rotation begins when a user clicks inside the window. ```java public class MyShapes extends Application { @@ -137,9 +136,9 @@ public class MyShapes extends Application { ``` -The `RotateTransition` constructor specifies a duration of 2500 milliseconds and applies the transition to the `StackPane` node. The rotation animation begins at angle 0 and proceeds linearly to angle 360, providing one full rotation. The animation starts when the user clicks anywhere inside the `StackPane` layout control. +The [`RotateTransition`](javafxdoc:RotateTransition) constructor specifies a duration of 2500 milliseconds and applies the transition to the [`StackPane`](javafxdoc:StackPane) node. The rotation animation begins at angle 0 and proceeds linearly to angle 360, providing one full rotation. The animation starts when the user clicks anywhere inside the [`StackPane`](javafxdoc:StackPane) layout control. -There are a few interesting things to notice in this example. First, because we define the transition on the `StackPane` node, the rotation applies to all of the `StackPane`’s children. This means that not only will the `Ellipse` and `Text` shapes rotate, but the drop shadow and reflection effects rotate, too. +There are a few interesting things to notice in this example. First, because we define the transition on the [`StackPane`](javafxdoc:StackPane) node, the rotation applies to all of the [`StackPane`](javafxdoc:StackPane)’s children. This means that not only will the [`Ellipse`](javafxdoc:Ellipse) and [`Text`](javafxdoc:Text) shapes rotate, but the drop shadow and reflection effects rotate, too. Second, the event handler checks the transition status. If the animation is in progress (running), the event handler pauses the transition. If it’s not running, it starts it up with `play()`. Because `play()` starts at the transition’s current time, a `pause()` followed by `play()` resumes the transition where it was paused. diff --git a/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/04_javafx_properties.md b/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/04_javafx_properties.md index 73d9a60..c9f1d62 100644 --- a/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/04_javafx_properties.md +++ b/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/04_javafx_properties.md @@ -26,15 +26,15 @@ byline: 'and is from   ## Invalidation Listeners Invalidation listeners have a single method that you override with lambda expressions. Let’s show you the non-lambda expression first, so you can see the full method definition. -When you click the `StackPane`, the mouse click handler rotates the `StackPane` control as before. The second `Text` object displays the status of the `RotationTransition` animation, which is managed by the read-only status property. +When you click the [`StackPane`](javafxdoc:StackPane), the mouse click handler rotates the [`StackPane`](javafxdoc:StackPane) control as before. The second [`Text`](javafxdoc:Text) object displays the status of the [`RotationTransition`](javafxdoc:RotationTransition) animation, which is managed by the read-only status property. You’ll see either RUNNING, PAUSED, or STOPPED. The figure below shows the animation paused. [![MyShapesProperties application with an invalidation listener](/assets/images/javafx/myshapes-properties-invalidation.png)](/assets/images/javafx/myshapes-properties-invalidation.png) @@ -113,8 +113,8 @@ The simplest form of binding links the value of one property to the value of ano text2.rotateProperty().bind(stackPane.rotateProperty()); ``` -This means any changes to `stackPane`’s rotation will immediately update text2’s rotate property. When this binding is set in the `MyShapesProperties` program, any clicks inside the `StackPane` initiate a rotate transition. -This makes both the `StackPane` and text2 components rotate together. The `StackPane` rotates because we start the `RotateTransition` defined for that node. The text2 node rotates because of the bind expression. +This means any changes to `stackPane`’s rotation will immediately update text2’s rotate property. When this binding is set in the `MyShapesProperties` program, any clicks inside the [`StackPane`](javafxdoc:StackPane) initiate a rotate transition. +This makes both the [`StackPane`](javafxdoc:StackPane) and text2 components rotate together. The [`StackPane`](javafxdoc:StackPane) rotates because we start the `RotateTransition` defined for that node. The text2 node rotates because of the bind expression. Note that when you bind a property, you cannot explicitly set its value unless you unbind the property first.   @@ -132,14 +132,14 @@ Bidirectional binding is not completely symmetrical; the initial value of both p ## Fluent API and Bindings API The fluent and bindings APIs help you construct bind expressions when more than one property needs to participate in a binding or when it’s necessary to perform some sort of calculation or conversion. -For example, the following bind expression displays the rotation angle of the `StackPane` as it rotates from 0 to 360 degrees. The text property is a `String`, and the rotate property is a double. -The binding method `asString()` converts the double to `String`, formatting the number with a single digit to the right of the decimal point: +For example, the following bind expression displays the rotation angle of the [`StackPane`](javafxdoc:StackPane) as it rotates from 0 to 360 degrees. The text property is a `String`, and the rotate property is a double. +The binding method `asString()` converts the double to [`String`](javadoc:String), formatting the number with a single digit to the right of the decimal point: ```java text2.textProperty().bind(stackPane.rotateProperty().asString("%.1f")); ``` -For a more complex example, let’s update `text2`’s stroke property (its color) depending on whether the animation is running or not. Here we construct a binding with `When` based on a ternary expression. +For a more complex example, let’s update `text2`’s stroke property (its color) depending on whether the animation is running or not. Here we construct a binding with [`When`](javafxdoc:When) based on a ternary expression. This sets the stroke color to green when the animation is running and to red when the animation is stopped or paused: ```java diff --git a/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/05_fxml.md b/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/05_fxml.md index 257a77e..c58e4a1 100644 --- a/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/05_fxml.md +++ b/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/05_fxml.md @@ -30,7 +30,7 @@ You’ve seen how JavaFX APIs create scene graph nodes and configure them for yo * You can design your UI with Scene Builder. This drag-and-drop tool is a stand-alone application that provides a visual rendering of your scene. And Scene Builder generates the FXML markup for you. * You can also edit your FXML markup with text and IDE editors. -FXML affects the structure of your program. The main application class now invokes an `FXMLLoader`. This loader parses your FXML markup, creates JavaFX objects, and inserts the scene graph into the scene at the root node. You can have multiple FXML files, and typically each one has a corresponding JavaFX controller class. This controller class may include event handlers or other statements that dynamically update the scene. +FXML affects the structure of your program. The main application class now invokes an [`FXMLLoader`](javafxdoc:FXMLLoader). This loader parses your FXML markup, creates JavaFX objects, and inserts the scene graph into the scene at the root node. You can have multiple FXML files, and typically each one has a corresponding JavaFX controller class. This controller class may include event handlers or other statements that dynamically update the scene. The controller also includes business logic that manages a specific view. Let’s return to our `MyShapes` example (now called `MyShapesFXML`) and use an FXML file for the view and CSS for styling. Below you can see the files in our program, arranged for use with build tools or IDEs. @@ -39,7 +39,7 @@ Let’s return to our `MyShapes` example (now called `MyShapesFXML`) and use an The JavaFX source code appears under the java subdirectory. The resources subdirectory contains the FXML and CSS files (here `Scene.fxml` and `Styles.css`). -This program includes a rotating `StackPane`, `VBox` control, and second `Text` object. `Scene.fxml` describes our scene graph: a top-level `VBox` that includes a `StackPane` and `Text` element. The `StackPane` includes the `Ellipse` and `Text` shapes. +This program includes a rotating [`StackPane`](javafxdoc:StackPane), [`VBox`](javafxdoc:VBox) control, and second [`Text`](javafxdoc:Text) object. `Scene.fxml` describes our scene graph: a top-level [`VBox`](javafxdoc:VBox) that includes a [`StackPane`](javafxdoc:StackPane) and [`Text`](javafxdoc:Text) element. The [`StackPane`](javafxdoc:StackPane) includes the [`Ellipse`](javafxdoc:Ellipse) and [`Text`](javafxdoc:Text) shapes. ```xml @@ -92,15 +92,15 @@ This program includes a rotating `StackPane`, `VBox` control, and second `Text` ``` -The top-level container includes the name of the JavaFX controller class with attribute fx:controller. The `VBox` specifies its alignment, preferred sizes, and spacing followed by its children: the `StackPane` and `Tex`t. -Here, we configure the `StackPane` with preferred sizing. A special attribute `fx:id` specifies a variable name corresponding to this node. -In the JavaFX controller class, you’ll now see this variable name annotated with `@FXML` for the `StackPane`. This is how you access objects in the controller class that are declared in FXML files. +The top-level container includes the name of the JavaFX controller class with attribute fx:controller. The [`VBox`](javafxdoc:VBox) specifies its alignment, preferred sizes, and spacing followed by its children: the [`StackPane`](javafxdoc:StackPane) and [`Text`](javafxdoc:StackPane). +Here, we configure the [`StackPane`](javafxdoc:StackPane) with preferred sizing. A special attribute `fx:id` specifies a variable name corresponding to this node. +In the JavaFX controller class, you’ll now see this variable name annotated with `@FXML` for the [`StackPane`](javafxdoc:StackPane). This is how you access objects in the controller class that are declared in FXML files. -In addition, `StackPane` specifies an `onMouseClicked` event handler called `#handleMouseClick`. This event handler is also annotated with `@FXML` in the JavaFX controller class. +In addition, [`StackPane`](javafxdoc:StackPane) specifies an `onMouseClicked` event handler called `#handleMouseClick`. This event handler is also annotated with `@FXML` in the JavaFX controller class. -Here, the `StackPane` children, `Ellipse` and `Text`, are declared inside the Children FXML node. Neither has associated `fx:id` attributes, since the controller class does not need to access these objects. You also see the linear gradient, drop shadow, and reflection effect configurations. +Here, the [`StackPane`](javafxdoc:StackPane) children, [`Ellipse`](javafxdoc:Ellipse) and [`Text`](javafxdoc:Text), are declared inside the Children FXML node. Neither has associated `fx:id` attributes, since the controller class does not need to access these objects. You also see the linear gradient, drop shadow, and reflection effect configurations. -Note that the `Text` object with `fx:id text2` appears after the `StackPane` definition. This makes the second `Text` object appear under the `StackPane` in the `VBox`. We also specify an `fx:id` attribute to access this node from the JavaFX controller. +Note that the [`Text`](javafxdoc:Text) object with `fx:id text2` appears after the [`StackPane`](javafxdoc:StackPane) definition. This makes the second [`Text`](javafxdoc:Text) object appear under the [`StackPane`](javafxdoc:StackPane) in the [`VBox`](javafxdoc:VBox). We also specify an `fx:id` attribute to access this node from the JavaFX controller.   ## Controller Class @@ -152,17 +152,17 @@ public class FXMLController implements Initializable { } ``` -The controller class implements `Initializable` and overrides method `initialize()`, which is invoked for you at runtime. Importantly, the private class fields `stackPane` and `text2` are annotated with `@FXML`. -The `@FXML` annotation associates variable names in the controller class to the objects described in the FXML file. There is no code in the controller class that creates these objects because the `FXMLLoader` does that for you. +The controller class implements [`Initializable`](javafxdoc:Initializable) and overrides method `initialize()`, which is invoked for you at runtime. Importantly, the private class fields `stackPane` and `text2` are annotated with `@FXML`. +The `@FXML` annotation associates variable names in the controller class to the objects described in the FXML file. There is no code in the controller class that creates these objects because the [`FXMLLoader`](javafxdoc:FXMLLoader) does that for you. -The `initialize()` method does three things here. First, it creates and configures the `RotateTransition` and applies it to the `stackPane` node. Second, it adds a change listener to the transition’s status property. +The `initialize()` method does three things here. First, it creates and configures the [`RotateTransition`](javafxdoc:RotateTransition) and applies it to the `stackPane` node. Second, it adds a change listener to the transition’s status property. And third, a bind expression for the `text2` stroke property specifies its color based on the rotate transition’s status. The `@FXML` annotation with `handleMouseClick()` indicates that the FXML file configures the event handler. This mouse click event handler starts and stops the rotate transition’s animation.   ## JavaFX Application Class -The main application class, `MyShapesFXML`, now becomes very simple. Its job is to invoke the `FXMLLoader`, which parses the FXML (`Scene.fxml`), builds the scene graph, and returns the scene graph root. All you have to do is build the scene object and configure the stage as before, as shown below. +The main application class, `MyShapesFXML`, now becomes very simple. Its job is to invoke the [`FXMLLoader`](javafxdoc:FXMLLoader), which parses the FXML (`Scene.fxml`), builds the scene graph, and returns the scene graph root. All you have to do is build the scene object and configure the stage as before, as shown below. ```java package org.modernclient; @@ -207,7 +207,7 @@ To use this stylesheet, you must first load the file, either in the application text2.getStyleClass().add("mytext"); ``` -Here, `mytext` is the style class and `text2` is the second `Text` object in our program. +Here, `mytext` is the style class and `text2` is the second [`Text`](javafxdoc:Text) object in our program. Alternatively, you can specify the stylesheet in the FXML file. The advantage of this approach is that styles are now available inside Scene Builder. Here is the modified `Scene.fxml` file that loads this customized CSS file and applies the customized CSS style class to the `text2 Text` node: ```xml @@ -240,7 +240,7 @@ Scene Builder is a stand-alone drag-and-drop tool for creating JavaFX UIs. You c The upper-left window shows the JavaFX component library. This library includes containers, controls, shapes, 3D, and more. From this window, you select components and drop them onto your scene in the middle visual view or onto the `Document` window shown in the lower-left area. -The `Document` window shows the scene graph hierarchy. You can select components and move them within the tree. The right window is an `Inspector` window that lets you configure each component, including its properties, layout settings, and code. In this figure, the `StackPane` is selected in the `Document` hierarchy window and appears in the center visual view. +The `Document` window shows the scene graph hierarchy. You can select components and move them within the tree. The right window is an `Inspector` window that lets you configure each component, including its properties, layout settings, and code. In this figure, the [`StackPane`](javafxdoc:StackPane) is selected in the `Document` hierarchy window and appears in the center visual view. In the `Inspector` window, the `OnMouseClicked` property is set to `#handleMouseClick`, which is the name of the corresponding method in the JavaFX controller class. Scene Builder is particularly helpful when building real-world form-based UIs. You can visualize your scene hierarchy and easily configure layout and alignment settings. diff --git a/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/06_all_together.md b/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/06_all_together.md index af66631..4f6a7a9 100644 --- a/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/06_all_together.md +++ b/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/06_all_together.md @@ -30,21 +30,21 @@ byline: 'and is from   ## Master-Detail UI -For the UI, we use a JavaFX ListView control in the left window (the master view) and a `Form` on the right (the detail view). In Scene Builder, we select an `AnchorPane` as the top-level component and the scene graph root. -A `SplitPane` layout pane divides the application view into two parts, and each part has `AnchorPane` as its main container. +For the UI, we use a JavaFX ListView control in the left window (the master view) and a Form on the right (the detail view). In Scene Builder, we select an [`AnchorPane`](javafxdoc:AnchorPane) as the top-level component and the scene graph root. +A [`SplitPane`](javafxdoc:SplitPane) layout pane divides the application view into two parts, and each part has [`AnchorPane`](javafxdoc:AnchorPane) as its main container. [![Person UI application](/assets/images/javafx/person-ui-app.png)](/assets/images/javafx/person-ui-app.png) -The `ListView` control lets you perform selections for a `Person` object. Here, the first `Person` is selected, and the details of that `Person` appear in the form control on the right. +The [`ListView`](javafxdoc:ListView) control lets you perform selections for a `Person` object. Here, the first `Person` is selected, and the details of that `Person` appear in the form control on the right. The form control has the following layout: -* The form contains a `GridPane` (two columns by four rows) that holds `TextFields` for the firstname and lastname fields of `Person`. -* A `TextArea` holds the notes field for `Person`. Labels in the first column mark each of these controls. -* The bottom row of the `GridPane` consists of a `ButtonBar` that spans both columns and aligns on the right side by default. The `ButtonBar` sizes all of its buttons to the width of the widest button label so the buttons have a uniform size. +* The form contains a [`GridPane`](javafxdoc:GridPane) (two columns by four rows) that holds [`TextField`](javafxdoc:TextField)s for the firstname and lastname fields of `Person`. +* A [`TextArea`](javafxdoc:TextArea) holds the notes field for `Person`. Labels in the first column mark each of these controls. +* The bottom row of the [`GridPane`](javafxdoc:GridPane) consists of a [`ButtonBar`](javafxdoc:ButtonBar) that spans both columns and aligns on the right side by default. The [`ButtonBar`](javafxdoc:ButtonBar) sizes all of its buttons to the width of the widest button label so the buttons have a uniform size. * The buttons let you perform New (create a `Person` and add that `Person` to the list), Update (edit a selected `Person`), and Delete (remove a selected `Person` from the list). * Bind expressions query the state of the application and enable or disable the buttons. @@ -132,15 +132,15 @@ public class Person {   ## Observable Lists -When working with JavaFX collections, you’ll typically use `ObservableLists` that detect list changes with listeners. Furthermore, the JavaFX controls that display lists of data expect observable lists. +When working with JavaFX collections, you’ll typically use [`ObservableList`](javafxdoc:ObservableList)s that detect list changes with listeners. Furthermore, the JavaFX controls that display lists of data expect observable lists. These controls automatically update the UI in response to list modifications. We’ll explain some of these intricacies as we walk you through our example program.   ## Implementing ListView Selection -A `ListView` control displays items in an observable list and lets you select one or possibly multiple items. To display a selected `Person` in the form fields in the right view, you use a change listener for the `selectedItemProperty`. -This change listener is invoked each time the user either selects a different item from the `ListView` or deselects the selected item. You can use the mouse for selecting, as well as the arrow keys, Home (for the first item), and End (for the last item). +A [`ListView`](javafxdoc:ListView) control displays items in an observable list and lets you select one or possibly multiple items. To display a selected `Person` in the form fields in the right view, you use a change listener for the `selectedItemProperty`. +This change listener is invoked each time the user either selects a different item from the [`ListView`](javafxdoc:ListView) or deselects the selected item. You can use the mouse for selecting, as well as the arrow keys, Home (for the first item), and End (for the last item). On a Mac, use Fn + Left Arrow for Home and Fn + Right Arrow for End. For deselecting (either Command-click for a Mac or Control-click on Linux or Windows), the new value is null, and we clear all the form control fields. -Below you can observe the `ListView` selection change listener. +Below you can observe the [`ListView`](javafxdoc:ListView) selection change listener. ```java listView.getSelectionModel().selectedItemProperty().addListener( @@ -161,11 +161,11 @@ listView.getSelectionModel().selectedItemProperty().addListener( }); ``` -Boolean property `modifiedProperty` tracks whether the user has changed any of the three text controls in the form. We reset this flag after each `ListView` selection and use this property in a bind expression to control the Update button’s disable property. +Boolean property `modifiedProperty` tracks whether the user has changed any of the three text controls in the form. We reset this flag after each [`ListView`](javafxdoc:ListView) selection and use this property in a bind expression to control the Update button’s disable property.   ## Using Multiple Selection -By default, a `ListView` control implements single selection so at most one item can be selected. `ListView` also provides multiple selection, which you enable by configuring the selection mode, as follows: +By default, a [`ListView`](javafxdoc:ListView) control implements single selection so at most one item can be selected. [`ListView`](javafxdoc:ListView) also provides multiple selection, which you enable by configuring the selection mode, as follows: ```java listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); @@ -186,8 +186,8 @@ Our Person UI application uses single selection mode for the ListView.   ## ListView and Sort -Suppose you want to sort the list of names by last name and then first name. JavaFX has several ways to sort lists. Since we need to keep names sorted, we’ll wrap the underlying `ObservableArrayList` in a `SortedList`. -To keep the list sorted in ListView, we invoke `ListView`’s setItems() method with the sorted list. A comparator specifies the ordering. +Suppose you want to sort the list of names by last name and then first name. JavaFX has several ways to sort lists. Since we need to keep names sorted, we’ll wrap the underlying `ObservableArrayList` in a [`SortedList`](javafxdoc:SortedList). +To keep the list sorted in ListView, we invoke [`ListView`](javafxdoc:ListView)’s setItems() method with the sorted list. A comparator specifies the ordering. First, we compare each person’s last name for sorting and then the first names if necessary. To set the sorting, the `setComparator()` method uses an anonymous class or, more succinctly, a lambda expression: ```java @@ -203,7 +203,7 @@ sortedList.setComparator((p1, p2) -> { listView.setItems(sortedList); ``` -Note that the comparator arguments p1 and p2 are inferred as `Person` types since `SortedList` is generic. +Note that the comparator arguments p1 and p2 are inferred as `Person` types since [`SortedList`](javafxdoc:SortedList) is generic.   ## Person UI Application Actions @@ -228,7 +228,7 @@ When mnemonic parsing is true, you can specify a keyboard shortcut to activate a --- -You cannot update a `SortedList` directly, but you can apply changes to its underlying list (`ObservableList personList`). The `SortedList` always keeps its elements sorted whenever you add or delete items. +You cannot update a [`SortedList`](javafxdoc:SortedList) directly, but you can apply changes to its underlying list (`ObservableList personList`). The [`SortedList`](javafxdoc:SortedList) always keeps its elements sorted whenever you add or delete items. Here is the event handler in the controller class: @@ -239,7 +239,7 @@ private void removeButtonAction(ActionEvent actionEvent) { } ``` -This handler removes the selected `Person` object from the backing observable array list. The `ListView` control’s selection change listener sets `selectedPerson`. +This handler removes the selected `Person` object from the backing observable array list. The [`ListView`](javafxdoc:ListView) control’s selection change listener sets `selectedPerson`. Note that we don’t have to check `selectedPerson` against null here. Why not? You’ll see that we disable the Delete button when the `selectedItemProperty` is null. This means the Delete button’s action event handler can never be invoked when the user deselects an element in the ListView control. Here’s the bind expression that controls the Delete button’s disable property: @@ -254,7 +254,7 @@ You can therefore use them in bind expressions. The property that invokes `bind( ### Add a Person -The New button adds a `Person` to the list and subsequently updates the `ListView` control. A new item is always sorted because the list re-sorts when elements are added to the wrapped list. +The New button adds a `Person` to the list and subsequently updates the [`ListView`](javafxdoc:ListView) control. A new item is always sorted because the list re-sorts when elements are added to the wrapped list. Here is the FXML that defines the New button. Similar to the Delete button, we define both the `fx:id` and `onAction` attributes: ```java @@ -262,7 +262,7 @@ Here is the FXML that defines the New button. Similar to the Delete button, we d ``` Under what circumstances should we disable the New button? -* When clicking New, no items in the `ListView` should be selected. Therefore, we disable the New button if the `selectedItemProperty` is not null. Note that you can deselect the selected item with Command-click or Control-click. +* When clicking New, no items in the [`ListView`](javafxdoc:ListView) should be selected. Therefore, we disable the New button if the `selectedItemProperty` is not null. Note that you can deselect the selected item with Command-click or Control-click. * We should not create a new `Person` if either the first or last name field is empty. So we disable the New button if either of these fields is empty. We do allow the Notes field to be empty, however. Here is the bind expression that implements these restrictions: @@ -301,7 +301,7 @@ By default, a sorted list does not respond to individual array elements that cha There’s two ways to fix this. First is to remove the item and add it back again with the new values. The second way is to define an extractor for the underlying object. An extractor defines properties that should be observed when changes occur. Normally, changes to individual list elements are not observed. Observable objects returned by the extractor flag update changes in a list ChangeListener. -Thus, to make a `ListView` control display a properly sorted list after changes to individual elements, you need to define an `ObservableList` with an extractor. +Thus, to make a [`ListView`](javafxdoc:ListView) control display a properly sorted list after changes to individual elements, you need to define an [`ObservableList`](javafxdoc:ObservableList) with an extractor. The benefit of extractors is that you only include the properties that affect sorting. In our example, properties firstname and lastname affect the list’s order. These properties should go in the extractor. @@ -315,7 +315,7 @@ public class Person { } ``` -Now the controller class can use this extractor to declare an `ObservableList` called `personList`, as follows: +Now the controller class can use this extractor to declare an [`ObservableList`](javafxdoc:ObservableList) called `personList`, as follows: ```java private final ObservableList personList = @@ -332,7 +332,7 @@ We initialize this Boolean to false in the JavaFX controller class, as follows: private final BooleanProperty modifiedProperty = new SimpleBooleanProperty(false); ``` -We reset this Boolean property to false in the `ListView` selection change listener. The `modifiedProperty` is set to true when a keystroke occurs in any of the three fields that can change: the first name, last name, and notes controls. +We reset this Boolean property to false in the [`ListView`](javafxdoc:ListView) selection change listener. The `modifiedProperty` is set to true when a keystroke occurs in any of the three fields that can change: the first name, last name, and notes controls. Here is the keystroke event handler, which is invoked when a key stroke is detected inside the focus for each of these three controls: ```java @@ -342,7 +342,7 @@ private void handleKeyAction(KeyEvent keyEvent) { } ``` -Of course, the FXML markup must configure attribute `onKeyReleased` for all three text controls to invoke the keystroke event handler. Here is the FXML for the firstname `TextField`, which links the `handleKeyAction` event handler to a key release event for this control: +Of course, the FXML markup must configure attribute `onKeyReleased` for all three text controls to invoke the keystroke event handler. Here is the FXML for the firstname [`TextField`](javafxdoc:TextField), which links the `handleKeyAction` event handler to a key release event for this control: ```xml ${text}`; + } + } + if (href.includes("doc:")) { let doc_id = href.match(/doc:([\w\.\-(),]+)/); From 84dfce33ffba327d1c26e4443a3889eb0b9a1065 Mon Sep 17 00:00:00 2001 From: Ana Date: Wed, 13 Sep 2023 19:47:07 +0200 Subject: [PATCH 2/3] Fix json typo --- app/data/javafxdoc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/data/javafxdoc.json b/app/data/javafxdoc.json index 2ffaf94..00fd762 100644 --- a/app/data/javafxdoc.json +++ b/app/data/javafxdoc.json @@ -54,5 +54,5 @@ "Initializable": "javafx/fxml/Initializable.html", "ObservableList": "javafx/collections/ObservableList.html", - "SortedList": "javafx/collections/transformation/SortedList.html", + "SortedList": "javafx/collections/transformation/SortedList.html" } \ No newline at end of file From 00f6a2eeba82b44472fa49886416796e8d209932 Mon Sep 17 00:00:00 2001 From: Ana Date: Thu, 14 Sep 2023 10:25:14 +0200 Subject: [PATCH 3/3] Update links to their correct location. --- app/data/javafxdoc.json | 78 +++++++++---------- .../01_javafx/06_all_together.md | 2 +- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/app/data/javafxdoc.json b/app/data/javafxdoc.json index 00fd762..091e54c 100644 --- a/app/data/javafxdoc.json +++ b/app/data/javafxdoc.json @@ -1,58 +1,58 @@ { "current_release": "19", - "javafx-documentation": "https://openjfx.io/javadoc/@@CURRENT_RELEASE@@/javafx.graphics/", - "javafxdoc_root": "https://openjfx.io/javadoc/@@CURRENT_RELEASE@@/javafx.graphics/", + "javafx-documentation": "https://openjfx.io/javadoc/@@CURRENT_RELEASE@@/", + "javafxdoc_root": "https://openjfx.io/javadoc/@@CURRENT_RELEASE@@/", - "Application": "javafx/application/Application.html", + "Application": "javafx.graphics/javafx/application/Application.html", - "Scene": "javafx/scene/Scene.html", + "Scene": "javafx.graphics/javafx/scene/Scene.html", - "Stage": "javafx/stage/Stage.html", + "Stage": "javafx.graphics/javafx/stage/Stage.html", - "Group": "javafx/scene/Group.html", + "Group": "javafx.graphics/javafx/scene/Group.html", - "AnchorPane": "javafx/scene/layout/AnchorPane.html", - "BorderPane": "javafx/scene/layout/BorderPane.html", + "AnchorPane": "javafx.graphics/javafx/scene/layout/AnchorPane.html", + "BorderPane": "javafx.graphics/javafx/scene/layout/BorderPane.html", - "FlowPane": "javafx/scene/layout/FlowPane.html", - "GridPane": "javafx/scene/layout/GridPane.html", - "HBox": "javafx/scene/layout/HBox.html", - "StackPane": "javafx/scene/layout/StackPane.html", - "VBox": "javafx/scene/layout/VBox.html", + "FlowPane": "javafx.graphics/javafx/scene/layout/FlowPane.html", + "GridPane": "javafx.graphics/javafx/scene/layout/GridPane.html", + "HBox": "javafx.graphics/javafx/scene/layout/HBox.html", + "StackPane": "javafx.graphics/javafx/scene/layout/StackPane.html", + "VBox": "javafx.graphics/javafx/scene/layout/VBox.html", - "ImageView": "javafx/scene/image/ImageView.html", + "ImageView": "javafx.graphics/javafx/scene/image/ImageView.html", - "Color": "javafx/scene/paint/Color.html", - "LinearGradient": "javafx/scene/paint/LinearGradient.html", + "Color": "javafx.graphics/javafx/scene/paint/Color.html", + "LinearGradient": "javafx.graphics/javafx/scene/paint/LinearGradient.html", - "Ellipse": "javafx/scene/shape/Ellipse.html", - "Line": "javafx/scene/shape/Line.html", - "Path": "javafx/scene/shape/Path.html", - "Rectangle": "javafx/scene/shape/Rectangle.html", - "Shape": "javafx/scene/shape/Shape.html", - "Text": "javafx/scene/shape/Text.html", + "Ellipse": "javafx.graphics/javafx/scene/shape/Ellipse.html", + "Line": "javafx.graphics/javafx/scene/shape/Line.html", + "Path": "javafx.graphics/javafx/scene/shape/Path.html", + "Rectangle": "javafx.graphics/javafx/scene/shape/Rectangle.html", + "Shape": "javafx.graphics/javafx/scene/shape/Shape.html", + "Text": "javafx.graphics/javafx/scene/text/Text.html", - "Button": "javafx/scene/control/Button.html", - "ButtonBar": "javafx/scene/control/ButtonBar.html", - "ListView": "javafx/scene/control/ListView.html", - "SplitPane": "javafx/scene/control/SplitPane.html", - "TextField": "javafx/scene/control/TextField.html", - "TextArea": "javafx/scene/control/TextArea.html", + "Button": "javafx.controls/javafx/scene/control/Button.html", + "ButtonBar": "javafx.controls/javafx/scene/control/ButtonBar.html", + "ListView": "javafx.controls/javafx/scene/control/ListView.html", + "SplitPane": "javafx.controls/javafx/scene/control/SplitPane.html", + "TextField": "javafx.controls/javafx/scene/control/TextField.html", + "TextArea": "javafx.controls/javafx/scene/control/TextArea.html", - "Animation.Status": "javafx/animation/Animation.Status.html", - "RotateTransition": "javafx/animation/RotateTransition.html", - "ParallelTransition": "javafx/animation/ParallelTransition.html", - "PauseTransition": "javafx/animation/PauseTransition.html", - "SequentialTransition": "javafx/animation/SequentialTransition.html", - "Transition": "javafx/animation/Transition.html", + "Animation.Status": "javafx.graphics/javafx/animation/Animation.Status.html", + "RotateTransition": "javafx.graphics/javafx/animation/RotateTransition.html", + "ParallelTransition": "javafx.graphics/javafx/animation/ParallelTransition.html", + "PauseTransition": "javafx.graphics/javafx/animation/PauseTransition.html", + "SequentialTransition": "javafx.graphics/javafx/animation/SequentialTransition.html", + "Transition": "javafx.graphics/javafx/animation/Transition.html", - "When": "javafx/beans/binding/When.html", + "When": "javafx.base/javafx/beans/binding/When.html", + "ObservableList": "javafx.base/javafx/collections/ObservableList.html", + "SortedList": "javafx.base/javafx/collections/transformation/SortedList.html", - "FXMLLoader": "javafx/fxml/FXMLLoader.html", - "Initializable": "javafx/fxml/Initializable.html", + "FXMLLoader": "javafx.fxml/javafx/fxml/FXMLLoader.html", + "Initializable": "javafx.fxml/javafx/fxml/Initializable.html" - "ObservableList": "javafx/collections/ObservableList.html", - "SortedList": "javafx/collections/transformation/SortedList.html" } \ No newline at end of file diff --git a/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/06_all_together.md b/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/06_all_together.md index 4f6a7a9..3ebd253 100644 --- a/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/06_all_together.md +++ b/app/pages/learn/01_tutorial/07_rich_client_apps/01_javafx/06_all_together.md @@ -186,7 +186,7 @@ Our Person UI application uses single selection mode for the ListView.   ## ListView and Sort -Suppose you want to sort the list of names by last name and then first name. JavaFX has several ways to sort lists. Since we need to keep names sorted, we’ll wrap the underlying `ObservableArrayList` in a [`SortedList`](javafxdoc:SortedList). +Suppose you want to sort the list of names by last name and then first name. JavaFX has several ways to sort lists. Since we need to keep names sorted, we’ll wrap the underlying `observableArrayList` in a [`SortedList`](javafxdoc:SortedList). To keep the list sorted in ListView, we invoke [`ListView`](javafxdoc:ListView)’s setItems() method with the sorted list. A comparator specifies the ordering. First, we compare each person’s last name for sorting and then the first names if necessary. To set the sorting, the `setComparator()` method uses an anonymous class or, more succinctly, a lambda expression: