For your convenience Apress has placed some of the front matter material after the index. Please use the Bookmarks and Contents at a Glance links to access them. iii Contents at a Glance About the Author.....................................................................................................x About the Technical Reviewer ...............................................................................xi Acknowledgments ................................................................................................xii Introduction .........................................................................................................xiii Chapter 1: JavaFX Fundamentals ...........................................................................1 Chapter 2: Graphics with JavaFX..........................................................................69 Chapter 3: Media with JavaFX............................................................................111 Chapter 4: JavaFX on the Web............................................................................141 Index ...................................................................................................................175 xiii Introduction JavaFX 2.0 is Java’s next generation graphical user interface (GUI) toolkit for developers to rapidly build rich cross-platform applications. Built from the ground up, JavaFX takes advantage of modern GPUs through hardware-accelerated graphics while providing well-designed programming interfaces enabling developers to combine graphics, animation, and UI controls. The new JavaFX 2.0 is a pure Java language application programming interface (API). The key architectural strategies provided by JavaFX 2.0 API are the reuse of existing Java libraries and the bridging of communication between other languages that run on the JVM (Visage, Jython, Groovy, JRuby, and Scala). Nandini Ramani of Oracle plainly states the intended direction of JavaFX the platform in the following excerpt from the screencast, Introducing JavaFX 2.0: “The industry is moving toward multi-core/multi-threading [type] platforms with GPUs. JavaFX 2.0 leverages these attributes to improve execution efficiency and UI design flexibility. Our initial goal is to give architects and developers of enterprise applications a set of tools and APIs to help them build better data driven business applications.” —Nandini Ramani Oracle Corp. VP of Development, Java Client Platform Some History In 2005, Sun Microsystems acquired the company SeeBeyond, at which a certain software engineer by the name of Chris Oliver created a graphics-rich scripting language known as F3 (Form Follows Function). F3 was later unveiled by Sun Microsystems at the 2007 JavaOne conference as JavaFX. On April 20, 2009 Oracle Corporation announced the acquisition of Sun Microsystems, making Oracle the new steward of JavaFX. At JavaOne 2010, Oracle announced the JavaFX roadmap. As part of the road map, Oracle revealed its plans to phase out the JavaFX script language and re-create JavaFX for the Java language and platform. As promised based on the 2010 roadmap, JavaFX 2.0 SDK was released at JavaOne October 3, 2011. Oracle also announced its commitment to take steps to release JavaFX as an open-source product, thus allowing the community to help move the platform forward. Open-sourcing JavaFX will increase its adoption, enable a quicker turnaround time on bug fixes, and generate new enhancements. Table 0-1 shows the overall history of the major JavaFX releases. INTRODUCTION xiv Table 0-1. Historical Timeline of Major JavaFX Releases Release Date Version Platform Description December 4, 2008 1.0 Windows and MacOS JavaFX Script language, Production Suite, Media Playback February 12, 2009 1.1 Windows and MacOS New mobile development June 2, 2009 1.2 Windows, MacOS, Linux, Solaris Skinnable UI controls, Charting API, and performance improvements April 22. 2010 1.3 Windows, MacOS, Linux, Solaris JavaFX Composer, TV Emulator, Mobile Emulator October 3, 2011 2.0 Windows, MacOS Rewritten for the Java Language Approach in This Book The title of the book says it all: JavaFX 2.0 Introduction by Example. In this book, you will be learning the new JavaFX 2.0 capabilities by following practical recipe examples. These recipes will, in turn, provide you with the knowledge needed to create your own rich client applications. In the same tone with Java’s mantra “Write once, run anywhere,” JavaFX also preserves this same sentiment. Because JavaFX 2.0 is written entirely in Java the language, you will feel right at home. Most of the recipes can be compiled and run under Java 6. However, some recipes will take advantage of Java 7’s language enhancements, so Java 7 will be required. While working through this book with JavaFX 2.0 and Java 7, you will realize that the new APIs and language enhancements will help you to become a more productive developer. Having said this, I encourage you to explore all of Java 7’s new capabilities. To delve deeper into the new capabilities of Java 7, I recommend the book, Java 7 Recipes. On an added note, the recipes in this book can also be found in Java 7 Recipes. This book covers JavaFX 2.0’s fundamentals, graphics and animations, audio and video, and the Web. The fundamentals include how to install prerequisite software (JavaFX 2.0, NetBeans 7.1) and create simple user interfaces. You will also learn the basics of the scene graph, text nodes and font styles, shapes, colors, layouts, menus, UI controls, simple styling (CSS styling), binding expressions, background processes, keyboard shortcuts, and dialog boxes. Next, in graphics and animations you will encounter image handling, drag-and-drop operations, animation APIs, and UI theming (Look ‘n’ Feel). After graphics and animations, you will learn audio and video. This section will include creating an MP3 player, using a video player, responding to media events, handling media marker events, and synchronizing an animation with media events. Finally, you will be using JavaFX 2.0 to interoperate with web technologies such as HTML5, JavaScript, and XML. In this section, you will be learning how to embed JavaFX into a web page, rendering and dynamically manipulating HTML5 content, creating a weather application to respond to HTML events, and creating an RSS feed application using an embedded database (Derby). INTRODUCTION xv Who This Book Is For If you are a Java developer who desires to take your client-side applications to the next level, you will find this book your guide to help you begin creating usable and aesthetically pleasing user interfaces. If you want a particular platform that is not listed in the preceding table, don’t be too concerned because by the time you read this, JavaFX 2.0 should be available on your favorite OS. How This Book Is Structured This book is arranged in a natural progression that moves forward from beginner- to intermediate-level concepts. For the Java developer, none of the concepts mentioned in this book should be extremely difficult to figure out. This book’s recipes are presented in a problem-solution format. After a brief description of a practical and real-world problem, a step-by-step solution will explain which techniques will be best suited to solve the problem. Each recipe can be easily adapted to meet your own needs when developing a game, media player, or your usual enterprise application. The more experienced Java UI developer you are, the more freedom you have to jump around to different chapters and recipes throughout the book. However, any Java developer can naturally progress through the book and learn the skills needed to enhance everyday GUI applications. Downloading the Code Source code is available for the examples in this book. You can download that code from this book’s catalog page on the Apress web site. The URL is http://www.apress.com/9781430242574. The code will be in a .zip file that is organized by chapter. References Following are some online resources that will prove helpful as you begin your journey: Introducing JavaFX 2.0, by Nandini Ramani: http://medianetwork.oracle.com/video/player/1191127359001 Chris Oliver's weblog: http://blogs.oracle.com/chrisoliver/entry/f3 JavaFX Roadmap: http://javafx.com/roadmap/ OpenJDK Discussion About JavaFX, by Richard Bair: http://fxexperience.com/2011/10/openjdk- discussion-about-javafx/ JavaFX on Wikipedia: http://en.wikipedia.org/wiki/JavaFX C H A P T E R 1 1 JavaFX Fundamentals The JavaFX 2.0 API is Java’s next generation GUI toolkit for developers to build rich cross-platform applications. JavaFX 2.0 is based on a scene graph paradigm (retained mode) as opposed to the traditional immediate mode style rendering. JavaFX’s scene graph is a tree-like data structure that maintains vector-based graphic nodes. The goal of JavaFX is to be used across many types of devices such as mobile devices, smartphones, TVs, tablet computers, and desktops. Before the creation of JavaFX, the development of rich Internet applications (RIAs) involved the gathering of many separate libraries and APIs to achieve highly functional applications. These separate libraries include Media, UI controls, Web, 3D, and 2D APIs. Because integrating these APIs together can be rather difficult, the talented engineers at Sun Microsystems (now Oracle) created a new set of JavaFX libraries that roll up all the same capabilities under one roof. JavaFX is the Swiss Army Knife of GUIs (see Figure 1-1). JavaFX 2.0 is a pure Java (language) API that allows developers to leverage existing Java libraries and tools. Figure 1-1. JavaFX Depending on who you talk to, you will likely encounter different definitions of “user experience” (or in the UI world, UX). But one fact still remains; the users will always demand better content and increased usability from GUI applications. In light of this fact, developers and designers often work together to craft applications to fulfill this demand. JavaFX provides a toolkit that helps both the developer and designer (in some cases, they happen to be the same person) to create functional yet esthetically pleasing applications. Another thing to acknowledge is that if you are developing a game, media player, or the usual enterprise application, JavaFX will not only assist in developing richer UIs but you’ll also find that the APIs are extremely well designed to greatly improve developer productivity (I’m all about the user of the API’s perspective). Although this book doesn’t go through an exhaustive study of all of JavaFX 2.0’s capabilities, you will find common use cases that can help you build richer applications. Hopefully, these recipes can lead CHAPTER 1 JAVAFX FUNDAMENTALS 2 you in the right direction by providing practical and real-world examples. I also would like to encourage you to explore other resources to gain further insight into JavaFX. I highly recommend the book Pro JavaFX Platform (Apress, 2009) and the soon to released Pro JavaFX 2.0 Platform (Apress, 2012), which is an invaluable resource. These books go in depth to help you create professional grade applications. So without further ado, let’s get started, shall we? 1-1. Installing Required Software Problem You want to start developing JavaFX applications, but you don’t know what software is required to be installed. Solution You’ll need to install the following software in order to get started with JavaFX: • Java 7 JDK or greater • JavaFX 2.0 SDK • NetBeans IDE 7.1 or greater Note As of this writing, things are subject to change. To see additional requirements, refer to http://download.oracle.com/javafx/2.0/system_requirements/jfxpub-system_requirements.htm. As of this writing, things are subject to change. By the time you read this; you will likely find JavaFX able to run on your favorite OS. For this recipe, I assume that Java 7 is already installed so I won’t detail those installation steps. Following are steps to install all other required software components: 1. Download JavaFX 2.0 and NetBeans IDE 7.1.x from the following locations: • JavaFX 2.0 SDK: http://www.oracle.com/technetwork/java/javafx/downloads/index.html • NetBeans 7.1 beta SDK: http://netbeans.org 2. Install JavaFX 2.0 SDK. The screen in Figure 1-2 will appear once you’ve launched the JavaFX SDK Setup executable. Once you have launched the JavaFX SDK setup executable you will see the start of the wizard in Figure 1-2. CHAPTER 1 JAVAFX FUNDAMENTALS 3 Figure 1-2. JavaFX 2.0 SDK Setup Wizard 3. Next, you can specify the home directory of the JavaFX SDK by clicking the Browse button. Figure 1-3 shows the default location for the JavaFX SDK’s home directory. You might want to jot this location down in order to configure your CLASSPATH in Step 6. Figure 1-3 displays Setup Options, which allow you to specify the JavaFX 2.0 SDK’s home directory. Figure 1-3. JavaFX SDK home directory CHAPTER 1 JAVAFX FUNDAMENTALS 4 4. After you click Next, the components will install and the screen shown in Figure 1-4 will appear. Figure 1-4 displays the progress indicator installing the last components before completing. Figure 1-4. Completing the install 5. Install the NetBeans IDE, which includes the JavaFX 2.0 plug-in. When installing, you will follow the default wizard screens. For additional instructions, you may refer to http://netbeans.org/community/releases/71/install.html. 6. Configuring your environment variable CLASSPATH to include the JavaFX runtime library. The name and location of the runtime library is at \rt\lib\jfxrt.jar. (Linux uses the forward slash: /). How It Works This recipe shows how to install Java FX 2.0 and the NetBeans IDE onto the Windows platform. You may need to modify your steps slightly when installing JavaFX 2.0 on other operating systems as they become available. Although the steps described here are for NetBeans, you can also develop using other IDEs such as Eclipse, IntelliJ, or vi. While most of the example recipes were created using the NetBeans IDE, you can also compile and run JavaFX applications using the command-line prompt. To compile and run JavaFX applications using the command-line prompt you will need to configure your CLASSPATH. After you have followed the wizards to install the prerequisite software you will need to set your environment’s CLASSPATH variable to include the JavaFX runtime library /rt/lib/jfxrt.jar (Step 6). Setting this library will later assist in compiling and running JavaFX-based applications on the command-line. The following code configures your CLASSPATH environment variable based on your platform: CHAPTER 1 JAVAFX FUNDAMENTALS 5 Setting CLASSPATH on Windows Platforms set JAVAFX_HOME=C:\Program Files (x86)\Oracle\JavaFX 2.0 SDK set JAVA_HOME=C:\Program Files (x86)\Java\jdk1.7.0 set CLASSPATH=%JAVAFX_HOME%\rt\lib\jfxrt.jar;. Setting CLASSPATH on UNIX/Linux/Mac OS platforms # bash environments export JAVAFX_HOME= export CLASSPATH=$CLASSPATH:$JAVAFX_HOME/rt/lib/jfxrt.jar #csh environments setenv JAVAFX_HOME setenv CLASSPATH ${CLASSPATH}:${JAVAFX_HOME}/rt/lib/jfxrt.jar In recipe 1-2 you will learn how to create a simple Hello World application. Once your Hello World application is created, you will be able to compile and run a JavaFX-based application. 1-2. Creating a Simple User Interface Problem You want to create, code, compile, and run a simple JavaFX Hello World application. Solution #1 Develop a JavaFX HelloWorld application using the JavaFX project creation wizard in the NetBeans IDE. CREATING A JAVAFX HELLO WORLD APPLICATION IN NETBEANS To quickly get started with creating, coding, compiling, and running a simple JavaFX HelloWorld application using the NetBeans IDE, follow these steps: Launch NetBeans IDE. 1) On the File menu, select New Project. 2) Under Choose Project and Categories, select the JavaFX folder. 3) Under Projects, select Java FX Application, and click Next. 4) Specify HelloWorldMain for your project name. 5) Change or accept the defaults for the Project Location and Project Folder fields. CHAPTER 1 JAVAFX FUNDAMENTALS 6 6) Make sure the Create Application Class check box option is selected. Click Finish. 7) In the NetBeans IDE on the Projects tab, select the newly created project. Open the Project Properties dialog box to verify that the Source/Binary format settings are JDK 7. Click Sources under Categories. 8) While still in the Project Properties dialog box, under Categories, select Libraries to verify that the Java 7 and JavaFX platform are configured properly. Click the Manage Platforms button. Make sure a tab showing JavaFX libraries appears. Figure 1-5 depicts the JavaFX tab detailing its SDK home, Runtime, and Javadoc directory locations. Once verified, click the Close button. Figure 1-5 shows the Java Platform Manager window containing JavaFX as a managed platform included with JDK 7. Figure 1-5. Java Platform Manager 9) After closing the Java Platform Manager window, click OK to close the Project Properties window. 10) To run and test your JavaFX Hello World application, access the Run menu, and select Run Main Project or hit the F6 key. Shown in Figure 1-6 is a simple JavaFX Hello World application launched from the NetBeans IDE. CHAPTER 1 JAVAFX FUNDAMENTALS 7 Figure 1-6. JavaFX Hello World launched from the NetBeans IDE Solution #2 Use your favorite editor to code your JavaFX Hello World application. Once the Java file is created you will use the command-line prompt to compile and run your JavaFX application. Following are the steps to create a JavaFX Hello World application to be compiled and run on the command-line prompt. CREATING A JAVAFX HELLO WORLD APPLICATION IN ANOTHER IDE To quickly get started: 1. Copy and paste the following code into your favorite editor and save the file as HelloWorldMain.java. The following source code is a JavaFX Hello World application: package helloworldmain; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.stage.Stage; /** * * @author cdea */ public class HelloWorldMain extends Application { CHAPTER 1 JAVAFX FUNDAMENTALS 8 /** * @param args the command line arguments */ public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("Hello World"); Group root = new Group(); Scene scene = new Scene(root, 300, 250); Button btn = new Button(); btn.setLayoutX(100); btn.setLayoutY(80); btn.setText("Hello World"); btn.setOnAction(new EventHandler() { public void handle(ActionEvent event) { System.out.println("Hello World"); } }); root.getChildren().add(btn); primaryStage.setScene(scene); primaryStage.show(); } } 2. After saving the file named HelloWorldMain.java, on the command-line prompt you will navigate to the directory location of the file. 3. Compile the source code file HelloWorldMain.java using the Java compiler javac: javac -d . HelloWorldMain.java 4. Run and test your JavaFX Hello World application. Assuming you are located in the same directory as the HelloWorldMain.java file, type the following command to run your JavaFX Hello World application from the command-line prompt: java helloworldmain.HelloWorldMain Shown in Figure 1-7 is a simple JavaFX Hello World application launched from the command-line prompt. CHAPTER 1 JAVAFX FUNDAMENTALS 9 Figure 1-7. JavaFX Hello World launched from the command-line prompt How It Works Following are descriptions of the two solutions. Both solutions require prerequisite software. (I cover how to install required software in recipe 1-1.) In Solution #1 you will be creating a JavaFX application using the NetBeans IDE. Solution #2 allows you to choose your favorite editor and use the command- line prompt to compile and execute JavaFX programs. Solution #1 To create a simple JavaFX Hello World application, using the NetBeans you will use the JavaFX project creation wizard as specified in Steps 1 through 7. In Steps 8 through 10, you will verify two settings to ensure that the project is configured to compile and run JavaFX 2.0 applications properly. Finally, in Step 11 you will run the JavaFX Hello World application by selecting the Run Main Project menu option. You shouldn’t encounter any difficulty when following Steps 1 through 7. However, Steps 8 through 10 address a minor NetBeans bug that has to do with setting your project source/binary format to JDK 7 and making sure that the managed platform includes the JavaFX runtime libraries. If you are not experiencing this issue, the NetBeans team may have already corrected the problem. To be on the safe side, it wouldn’t hurt to follow Steps 8 through 10 to verify your configurations before you begin. Solution #2 To create a simple JavaFX Hello World application using your favorite IDE, follow Steps 1 and 2. To compile and run your Hello World program on the command line, follow Steps 3 and 4. Once the source code is entered into your favorite editor and the source file has been saved, you will want to compile and run your JavaFX program. Open the command-line prompt window and navigate to the directory location of the Java file named HelloWorldMain.java. Here I would like to point out the way you compile the file using the command javac -d . HelloWorldMain.java. You will notice the -d . before the file name. This lets the Java compiler know where to put class files based on their package name. In this scenario, the HelloWorldMain package statement is helloworldmain, which will create a subdirectory under the current directory. When finished compiling, your directory structure should resemble the following: CHAPTER 1 JAVAFX FUNDAMENTALS 10 |projects |helloworld |HelloWorldMain.java | helloworldmain |HelloWorldMain.class With the preceding directory structure in mind, the following commands will compile and run our JavaFX Hello World application: cd /projects/helloworld javac –d . HelloWorldMain.java java helloworldmain.HelloWorldMain Note There are many ways to package and deploy JavaFX applications. To learn more, please see “Learning how to deploy and package JavaFX applications” at http://blogs.oracle.com/thejavatutorials/entry/javafx_2_0_beta_packager. For in-depth JavaFX deployment strategies, see Oracle’s “Deploying JavaFX Applications” at http://download.oracle.com/javafx/2.0/deployment/deployment_toolkit.htm. In both solutions you’ll notice in the source code that JavaFX applications extend the javafx.application.Application class. The Application class provides application life cycle functions such as launching and stopping during runtime. This also provides a mechanism for Java applications to launch JavaFX GUI components in a threadsafe manner. Keep in mind that synonymous to Java Swing’s event dispatch thread, JavaFX will have its own JavaFX application thread. In our main() method’s entry point we launch the JavaFX application by simply passing in the command line arguments to the Application.launch() method. Once the application is in a ready state, the framework internals will invoke the start() method to begin. When the start() method is invoked, a JavaFX javafx.stage.Stage object is available for the developer to use and manipulate. You’ll notice that some objects are oddly named, such as Stage or Scene. The designers of the API have modeled things similar to a theater or a play in which actors perform in front of an audience. With this same analogy, in order to show a play, there are basically one-to-many scenes that actors perform in. And, of course, all scenes are performed on a stage. In JavaFX the Stage is equivalent to an application window similar to Java Swing API JFrame or JDialog. You may think of a Scene object as a content pane capable of holding zero-to-many Node objects. A Node is a fundamental base class for all scene graph nodes to be rendered. Commonly used nodes are UI controls and Shape objects. Similar to a tree data structure, a scene graph will contain children nodes by using a container class Group. We’ll learn more about the Group class later when we look at the ObservableList, but for now we can think of them as Java Lists or Collections that are capable of holding Nodes. Once the child nodes have been added, we set the primaryStage’s (Stage) scene and call the show() method on the Stage object to show the JavaFX window. One last thing: in this chapter most of the example applications will be structured the same as this example in which recipe code solutions will reside inside the start() method. Having said this, most of the recipes in this chapter will follow the same pattern. In other words, for the sake of brevity, much of CHAPTER 1 JAVAFX FUNDAMENTALS 11 the boiler plate code will not be shown. To see the full source listings of all the recipes, please download the source code from the book’s web site. 1-3: Drawing Text Problem You want to draw text onto the JavaFX scene graph. Solution Create Text nodes to be placed on the JavaFX scene graph by utilizing the javafx.scene.text.Text class. As Text nodes are to be placed on the scene graph, you decide you want to create randomly positioned Text nodes rotated around their (x, y) positions scattered about the scene area. The following code implements a JavaFX application that displays Text nodes scattered about the scene graph with random positions and colors: package javafx2introbyexample.chapter1.recipe1_03; import java.util.Random; import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.paint.Color; import javafx.scene.text.Text; import javafx.stage.Stage; /** * * @author cdea */ public class DrawingText extends Application { /** * @param args the command line arguments */ public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("Chapter 1-3 Drawing Text"); Group root = new Group(); Scene scene = new Scene(root, 300, 250, Color.WHITE); Random rand = new Random(System.currentTimeMillis()); for (int i = 0; i < 100; i++) { int x = rand.nextInt((int) scene.getWidth()); int y = rand.nextInt((int) scene.getHeight()); CHAPTER 1 JAVAFX FUNDAMENTALS 12 int red = rand.nextInt(255); int green = rand.nextInt(255); int blue = rand.nextInt(255); Text text = new Text(x, y, "JavaFX 2.0"); int rot = rand.nextInt(360); text.setFill(Color.rgb(red, green, blue, .99)); text.setRotate(rot); root.getChildren().add(text); } primaryStage.setScene(scene); primaryStage.show(); } } Figure 1-8 shows random Text nodes scattered about the JavaFX scene graph. Figure 1-8. Drawing text How It Works To draw text in JavaFX you will be creating a javafx.scene.text.Text node to be placed on the scene graph (javafx.scene.Scene). In this example you’ll notice text objects with random colors and positions scattered about the Scene area. First, we create a loop to generate random (x, y) coordinates to position Text nodes. Second, we create random color components between (0–255 rgb) to be applied to the Text nodes. Third, the rotation angle (in degrees) is a randomly generated value between (0–360 degrees) to cause the text to be slanted. The following code creates random values that will be assigned to a Text node’s position, color, and rotation: int x = rand.nextInt((int) scene.getWidth()); int y = rand.nextInt((int) scene.getHeight()); int red = rand.nextInt(255); CHAPTER 1 JAVAFX FUNDAMENTALS 13 int green = rand.nextInt(255); int blue = rand.nextInt(255); int rot = rand.nextInt(360); Once the random values are generated, they will be applied to the Text nodes, which will be drawn onto the scene graph. The following code snippet applies position (x, y), color (rgb), and rotation (angle in degrees) onto the Text node: Text text = new Text(x, y, "JavaFX 2.0"); text.setFill(Color.rgb(red, green, blue, .99)); text.setRotate(rot); root.getChildren().add(text); You will begin to see the power of the scene graph API by its ease of use. Text nodes can be easily manipulated as if they were Shapes. Well, actually they really are Shapes. Defined in the inheritance hierarchy, Text nodes extend from the javafx.scene.shape.Shape class and are therefore capable of doing interesting things such as being filled with colors or rotated about an angle. Although the text is colorized, they still tend to be somewhat boring. However, in the next recipe we will demonstrate how to change a text’s font. 1-4: Changing Text Fonts Problem You want to change text fonts and add special effect to Text nodes. Solution Create a JavaFX application that uses the following classes to set the text font and apply effects on Text nodes: • javafx.scene.text.Font • javafx.scene.effect.DropShadow • javafx.scene.effect.Reflection The code that follows sets the font and applies effects to Text nodes. We will be using the Serif, SanSerif, Dialog, and Monospaced fonts along with the drop shadow and reflection effects: package javafx2introbyexample.chapter1.recipe1_04; import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.effect.DropShadow; import javafx.scene.effect.Reflection; import javafx.scene.paint.Color; import javafx.scene.text.Font; import javafx.scene.text.Text; CHAPTER 1 JAVAFX FUNDAMENTALS 14 import javafx.stage.Stage; /** * Changing Text Fonts * @author cdea */ public class ChangingTextFonts extends Application { /** * @param args the command line arguments */ public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("Chapter 1-4 Changing Text Fonts"); Group root = new Group(); Scene scene = new Scene(root, 550, 250, Color.WHITE); // Serif with drop shadow Text text2 = new Text(50, 50, "JavaFX 2.0: Intro. by Example"); Font serif = Font.font("Serif", 30); text2.setFont(serif); text2.setFill(Color.RED); DropShadow dropShadow = new DropShadow(); dropShadow.setOffsetX(2.0f); dropShadow.setOffsetY(2.0f); dropShadow.setColor(Color.rgb(50, 50, 50, .588)); text2.setEffect(dropShadow); root.getChildren().add(text2); // SanSerif Text text3 = new Text(50, 100, "JavaFX 2.0: Intro. by Example"); Font sanSerif = Font.font("SanSerif", 30); text3.setFont(sanSerif); text3.setFill(Color.BLUE); root.getChildren().add(text3); // Dialog Text text4 = new Text(50, 150, "JavaFX 2.0: Intro. by Example"); Font dialogFont = Font.font("Dialog", 30); text4.setFont(dialogFont); text4.setFill(Color.rgb(0, 255, 0)); root.getChildren().add(text4); // Monospaced Text text5 = new Text(50, 200, "JavaFX 2.0: Intro. by Example"); Font monoFont = Font.font("Monospaced", 30); text5.setFont(monoFont); CHAPTER 1 JAVAFX FUNDAMENTALS 15 text5.setFill(Color.BLACK); root.getChildren().add(text5); Reflection refl = new Reflection(); refl.setFraction(0.8f); text5.setEffect(refl); primaryStage.setScene(scene); primaryStage.show(); } } Figure 1-9 shows the JavaFX application setting various font styles and applying effects (drop shadow and reflection) to the Text nodes. Figure 1-9. Changing text fonts How It Works In this recipe, I basically used JavaFX’s scene graph to display Text nodes. JavaFX takes a retained mode approach, in which nodes use vector-based graphics. Vector-based graphics allow you to scale shapes and apply effects without issues of pixilation (jaggies). In each Text node you can create and set the font to be rendered onto the scene graph. Here is the code to create and set the font on a Text node: Text text2 = new Text(50, 50, "JavaFX 2.0: Intro. by Example"); Font serif = Font.font("Serif", 30); text2.setFont(serif); The drop shadow is a real effect (DropShadow) object and actually applied to a single Text node instance. The DropShadow object is set to be positioned based on an x and y offset in relation to the Text node. Also we can set the color of the shadow; here we set it to gray with a .588 opacity. Following is an example of setting a Text node’s effect property with a drop shadow effect (DropShadow): DropShadow dropShadow = new DropShadow(); dropShadow.setOffsetX(2.0f); CHAPTER 1 JAVAFX FUNDAMENTALS 16 dropShadow.setOffsetY(2.0f); dropShadow.setColor(Color.rgb(50, 50, 50, .588)); text2.setEffect(dropShadow); Although this is about setting text fonts, we applied effects to Text nodes. I’ve added yet another effect (just kicking it up a notch). While creating the last Text node using the monospaced font, I applied the popular reflection effect. Here it is, set so that .8 or 80 percent of the reflection will be shown. The reflection values range from zero (0%) to one (100%). The following code snippet implements a reflection of 80% with a float value of 0.8f: Reflection refl = new Reflection(); refl.setFraction(0.8f); text5.setEffect(refl); 1-5. Creating Shapes Problem You want to create shapes to be placed on the scene graph. Solution Use JavaFX’s Arc, Circle, CubicCurve, Ellipse, Line, Path, Polygon, Polyline, QuadCurve, Rectangle, SVGPath, and Text classes in the javafx.scene.shape.* package. You may also use builder classes associated with each shape in the javafx.builders.* package. The following code draws various complex shapes. The first complex shape involves a cubic curve drawn in the shape of a sine wave. The next shape, which I would like to call the ice cream cone, uses the path class that contains path elements (javafx.scene.shape.PathElement). The third shape is a Quadratic Bézier curve (QuadCurve) forming a smile. Our final shape is a delectable donut. We create this donut shape by subtracting two ellipses (one smaller and one larger): // CubicCurve CubicCurve cubicCurve = CubicCurveBuilder.create() .startX(50).startY(75) // start pt (x1,y1) .controlX1(80).controlY1(-25) // control pt1 .controlX2(110).controlY2(175) // control pt2 .endX(140).endY(75) // end pt (x2,y2) .strokeType(StrokeType.CENTERED).strokeWidth(1) .stroke(Color.BLACK) .strokeWidth(3) .fill(Color.WHITE) .build(); root.getChildren().add(cubicCurve); // Ice cream Path path = new Path(); MoveTo moveTo = new MoveTo(); CHAPTER 1 JAVAFX FUNDAMENTALS 17 moveTo.setX(50); moveTo.setY(150); QuadCurveTo quadCurveTo = new QuadCurveTo(); quadCurveTo.setX(150); quadCurveTo.setY(150); quadCurveTo.setControlX(100); quadCurveTo.setControlY(50); LineTo lineTo1 = new LineTo(); lineTo1.setX(50); lineTo1.setY(150); LineTo lineTo2 = new LineTo(); lineTo2.setX(100); lineTo2.setY(275); LineTo lineTo3 = new LineTo(); lineTo3.setX(150); lineTo3.setY(150); path.getElements().add(moveTo); path.getElements().add(quadCurveTo); path.getElements().add(lineTo1); path.getElements().add(lineTo2); path.getElements().add(lineTo3); path.setTranslateY(30); path.setStrokeWidth(3); path.setStroke(Color.BLACK); root.getChildren().add(path); // QuadCurve create a smile QuadCurve quad =QuadCurveBuilder.create() .startX(50) .startY(50) .endX(150) .endY(50) .controlX(125) .controlY(150) .translateY(path.getBoundsInParent().getMaxY()) .strokeWidth(3) .stroke(Color.BLACK) .fill(Color.WHITE) .build(); root.getChildren().add(quad); // outer donut Ellipse bigCircle = EllipseBuilder.create() .centerX(100) .centerY(100) .radiusX(50) CHAPTER 1 JAVAFX FUNDAMENTALS 18 .radiusY(75/2) .translateY(quad.getBoundsInParent().getMaxY()) .strokeWidth(3) .stroke(Color.BLACK) .fill(Color.WHITE) .build(); // donut hole Ellipse smallCircle = EllipseBuilder.create() .centerX(100) .centerY(100) .radiusX(35/2) .radiusY(25/2) .build(); // make a donut Shape donut = Path.subtract(bigCircle, smallCircle); // orange glaze donut.setFill(Color.rgb(255, 200, 0)); // add drop shadow DropShadow dropShadow = new DropShadow(); dropShadow.setOffsetX(2.0f); dropShadow.setOffsetY(2.0f); dropShadow.setColor(Color.rgb(50, 50, 50, .588)); donut.setEffect(dropShadow); // move slightly down donut.setTranslateY(quad.getBoundsInParent().getMinY() + 30); root.getChildren().add(donut); Figure 1-10 displays the sine wave, ice cream cone, smile, and donut shapes that we have created using JavaFX: CHAPTER 1 JAVAFX FUNDAMENTALS 19 Figure 1-10. Creating shapes How It Works The first shape is a javafx.scene.shape.CubicCurve class. To create a cubic curve, you simply look for the appropriate constructor to be instantiated. A cubic curve’s main parameters that you will be setting are its start X, start Y, control point 1 X, control point 1 Y, control point 2 X, control point 2 Y, end X, end Y. The startX, startY, endX, endY parameters are the starting point and ending point of a curve. The controlX1, controlY1, controlX2, controlY2 denote control point 1 and control point 2. A control point is a point that pulls the curve towards the direction of the point itself. In our example, we simply have a control point 1 above to pull the curve upward to form a hill and control point 2 below to pull the curve downward to form a valley. The following illustration (Figure 1-11) depicts a Cubic Curve with control points influencing the curve: CHAPTER 1 JAVAFX FUNDAMENTALS 20 Figure 1-11. Cubic Curve The following code snippet is used to create a javafx.scene.shape.CubicCurve instance: CubicCurve cubicCurve = new CubicCurve(); cubicCurve.setStartX(50); // start pt (x1,y1) cubicCurve.setStartY(75); cubicCurve.setControlX1(80); // control pt1 cubicCurve.setControlY1(-25); cubicCurve.setControlX2(110); // control pt2 cubicCurve.setControlY2(175); cubicCurve.setEndX(140); // end pt (x2,y2) cubicCurve.setEndY(75); But, right off the bat in the source code listing in the solution section, you’ll notice that I didn’t use the usual new CubicCurve() constructor like the previous snippet, but instead I use a class having a suffix of Builder on the end of it. Builder classes are convenience classes that follow a design pattern called the Builder pattern. Builder classes provide a way to method chain invocations by enabling the developer to specify attributes in an ad hoc way (declarative). This makes code more readable and less verbose, thus increasing developer productivity. When using this facility while developing graphics applications, you may also find that coding tends to be more expressive and reminiscent of declarative type languages (Visage, Groovy, Scala, and Python). Back to CubicCurveBuilder; we begin with the create() method that will instantiate a Builder class. Next is specifying a cubic curve’s attributes in any order. Similar to mutators or setter methods, you simply pass a single value to the method. The convention is that the set prefixed on the method is removed, and the method returns the this pointer of the builder object instance. By returning itself it allows you to continue to use the dot notation to specify parameters, thus the method chaining behavior. Once finished with specifying values on the Builder class, a call to the build() method will return an instance of the desired class (in this case, the CubicCurve class). The ice cream cone shape is created using the javafx.scene.shape.Path class. As each path element is created and added to the Path object, each element is not considered a graph node (javafx.scene.Node). This means they do not extend from the javafx.scene.shape.Shape class and cannot be a child node in a scene graph to be displayed. When looking at the Javadoc, you will notice that a Path class extends from the Shape class that extends from the (javafx.scene.Node) class, and therefore a Path is a graph node, but path elements do not extend from the Shape class. Path elements actually extend from the javafx.scene.shape.PathElement class, which is only used in the context of a CHAPTER 1 JAVAFX FUNDAMENTALS 21 Path object. So you won’t be able to instantiate a LineTo class to be put in the scene graph. Just remember that the classes with To as a suffix is a path element, not a real Shape node. For example, the MoveTo and LineTo object instances are Path elements added to a Path object, not shapes that can be added to the scene. Shown following are Path elements added to a Path object to draw an ice cream cone: // Ice cream Path path = new Path(); MoveTo moveTo = new MoveTo(); moveTo.setX(50); moveTo.setY(150); ...// Additional Path Elements created. LineTo lineTo1 = new LineTo(); lineTo1.setX(50); lineTo1.setY(150); ...// Additional Path Elements created. path.getElements().add(moveTo); path.getElements().add(quadCurveTo); path.getElements().add(lineTo1); Rendering the QuadCurve (smile) object I used the QuadCurveBuilder class similar to the CubicCurveBuilder class, and you’ll notice the simplicity of creating such a shape. This is similar to the cubic curve example described above in the first shape. Instead of two control points you only have one control point. Shown below (Figure 1-12) is a QuadCurve shape with a control point below its starting and ending points: Figure 1-12. Quadratic Curve Once your builder class is complete you will finish things off by invoking the build() method. Shown below is a quadratic curve with a stroke thickness of three pixels filled with the color white: // QuadCurve create a smile QuadCurve quad =QuadCurveBuilder.create() .startX(50) .startY(50) .endX(150) .endY(50) CHAPTER 1 JAVAFX FUNDAMENTALS 22 .controlX(125) .controlY(150) .strokeWidth(3) .stroke(Color.BLACK) .fill(Color.WHITE) .build(); Last is our tasty donut shape with a drop shadow effect. When creating the donut, we begin by creating two circular ellipses. By subtracting the smaller ellipse (donut hole) from the larger ellipse area, a newly derived Shape object is created and returned using the Path.subtract() method. Following is the code snippet that creates the donut shape using the Path.subtract() method: // outer donut Ellipse bigCircle = ...//Outer shape area // donut hole Ellipse smallCircle = ...// Inner shape area // make a donut Shape donut = Path.subtract(bigCircle, smallCircle); Next, is applying a drop shadow effect onto our donut. A common technique is to draw the shape filled black while the original shape is laid on top slightly offset to appear as a shadow. However, in JavaFX we draw it once and use the setEffect() method to apply a DropShadow object instance. To cast the shadow offset call the setOffsetX() and setOffsetY() methods. One last thing to point out is that all shapes are drawn to be positioned underneath one another. As each shape was created, you’ll notice their translateY property was set to reposition or shift the shape from its original position. For example, if a shape’s upper left bounding box point is created at (100, 100) and you want it to be moved to (101, 101) the translateX and translateY properties would be set to one. 1-6. Assigning Colors to Objects Problem You want to fill your shapes with simple colors and gradient colors. Solution In JavaFX, all shapes can be filled with simple colors and gradient colors. The following are the main classes used to fill shape nodes: • javafx.scene.paint.Color • javafx.scene.paint.LinearGradient • javafx.scene.paint.Stop • javafx.scene.paint.RadialGradient CHAPTER 1 JAVAFX FUNDAMENTALS 23 The following code uses the preceding classes to add radial and linear gradient colors as well as transparent (alpha channel level) colors to our shapes. We will be using an ellipse, rectangle, and rounded rectangle in our recipe. A solid black line (as depicted in Figure 1-13) also appears in our recipe to demonstrate the transparency of our shape’s color. primaryStage.setTitle("Chapter 1-6 Assigning Colors To Objects"); Group root = new Group(); Scene scene = new Scene(root, 350, 300, Color.WHITE); Ellipse ellipse = new Ellipse(100, 50 + 70/2, 50, 70/2); RadialGradient gradient1 = RadialGradientBuilder.create() .focusAngle(0) .focusDistance(.1) .centerX(80) .centerY(45) .radius(120) .proportional(false) .cycleMethod(CycleMethod.NO_CYCLE) .stops(new Stop(0, Color.RED), new Stop(1, Color.BLACK)) .build(); ellipse.setFill(gradient1); root.getChildren().add(ellipse); Line blackLine = LineBuilder.create() .startX(170) .startY(30) .endX(20) .endY(140) .fill(Color.BLACK) .strokeWidth(10.0f) .translateY(ellipse.prefHeight(-1) + ellipse.getLayoutY() + 10) .build(); root.getChildren().add(blackLine); Rectangle rectangle = RectangleBuilder.create() .x(50) .y(50) .width(100) .height(70) .translateY(ellipse.prefHeight(-1) + ellipse.getLayoutY() + 10) .build(); LinearGradient linearGrad = LinearGradientBuilder.create() .startX(50) .startY(50) .endX(50) .endY(50 + rectangle.prefHeight(-1) + 25) CHAPTER 1 JAVAFX FUNDAMENTALS 24 .proportional(false) .cycleMethod(CycleMethod.NO_CYCLE) .stops( new Stop(0.1f, Color.rgb(255, 200, 0, .784)), new Stop(1.0f, Color.rgb(0, 0, 0, .784))) .build(); rectangle.setFill(linearGrad); root.getChildren().add(rectangle); Rectangle roundRect = RectangleBuilder.create() .x(50) .y(50) .width(100) .height(70) .arcWidth(20) .arcHeight(20) .translateY(ellipse.prefHeight(-1) + ellipse.getLayoutY() + 10 + rectangle.prefHeight(-1) + rectangle.getLayoutY() + 10) .build(); LinearGradient cycleGrad = LinearGradientBuilder.create() .startX(50) .startY(50) .endX(70) .endY(70) .proportional(false) .cycleMethod(CycleMethod.REFLECT) .stops(new Stop(0f, Color.rgb(0, 255, 0, .784)), new Stop(1.0f, Color.rgb(0, 0, 0, .784))) .build(); roundRect.setFill(cycleGrad); root.getChildren().add(roundRect); primaryStage.setScene(scene); primaryStage.show(); Figure 1-13 displays the various types of colorized fills that can be applied onto shapes. CHAPTER 1 JAVAFX FUNDAMENTALS 25 Figure 1-13. Color shapes How It Works Figure 1-13 shows shapes displayed from top to bottom starting with an ellipse, rectangle, and a rounded rectangle having colored gradient fills. When drawing the eclipse shape you will be using a radial gradient that appears as if it were a 3D spherical object. Next, you will be creating a rectangle filled with a yellow semitransparent linear gradient. A thick black line shape was drawn behind the yellow rectangle to demonstrate the rectangle’s semitransparent color. Last, you will implement a rounded rectangle filled with a green-and-black reflective linear gradient resembling 3D tubes in a diagonal direction. The amazing thing about colors with gradients is that they can often make shapes appear three- dimensional. Gradient paint allows you to interpolate between two or more colors, which gives depth to the shape. JavaFX provides two types of gradients: a radial (RadialGradient) and a linear (LinearGradient) gradient. For our ellipse shape you will be using a radial gradient (RadialGradient). I created Table 1-1 from the JavaFX 2.0 Javadoc definitions found for the RadialGradient class (http://download.oracle.com/javafx/2.0/api/javafx/scene/paint/RadialGradient.html). Table 1-1. RadialGradient Properties Property Data Type Description focusAngle double Angle in degrees from the center of the gradient to the focus point to which the first color is mapped focusDistance double Distance from the center of the gradient to the focus point to which the first color is mapped CHAPTER 1 JAVAFX FUNDAMENTALS 26 Property Data Type Description centerX double X coordinate of the center point of the gradient's circle centerY double Y coordinate of the center point of the gradient's circle radius double Radius of the circle defining the extents of the color gradient proportional boolean Coordinates and sizes are proportional to the shape which this gradient fills cycleMethod CycleMethod Cycle method applied to the gradient stops List Gradient's color specification In our recipe the focus angle is set to zero, distance is set to .1, center X and Y is set to (80,45), radius is set to 120 pixels, proportional is set to false, cycle method is set to the no cycle (CycleMethod.NO_CYCLE), and two color stop values set to red (Color.RED) and black (Color.BLACK). These settings give a radial gradient to our ellipse by starting with the color red with a center position of (80, 45) (upper left of the ellipse) that interpolates to the color black with a distance of 120 pixels (radius). Next, you will be creating a rectangle having a yellow semitransparent linear gradient. For our yellow rectangle you will be using linear gradient (LinearGradient) paint. I created Table 1-2 from the JavaFX 2.0 Javadoc definitions found for the LinearGradient class (http://download.oracle.com/javafx/2.0/api/javafx/scene/paint/LinearGradient.html). Table 1-2. LinearGradient Properties Property Data Type Description startX double X coordinate of the gradient axis start point startY double Y coordinate of the gradient axis start point endX double X coordinate of the gradient axis end point endY double Y coordinate of the gradient axis end point proportional boolean Whether the coordinates are proportional to the shape which this gradient fills cycleMethod CycleMethod Cycle method applied to the gradient stops List Gradient's color specification CHAPTER 1 JAVAFX FUNDAMENTALS 27 To create a linear gradient paint you will specify the startX, startY, endX, and endY for the start and end points. The start and end point coordinates denote where the gradient pattern begins and stops. To create the second shape (yellow rectangle) you will set the start X and Y to (50, 50), end X and Y to (50, 75), proportional to false, cycle method to no cycle (CycleMethod.NO_CYCLE), and two color stop values to yellow (Color.YELLOW) and black (Color.BLACK) with an alpha transparency of .784.These settings give a linear gradient to our rectangle from top to bottom with a starting point of (50, 50) (top left of rectangle) that interpolates to the color black (bottom left of rectangle). Finally, you’ll notice a rounded rectangle with a repeating pattern of a gradient using green and black in a diagonal direction. This is a simple linear gradient paint that is the same as the linear gradient paint (LinearGradient) except that the start X, Y and the end X, Y are set in a diagonal position, and the cycle method is set to reflect (CycleMethod.REFLECT). When specifying the cycle method to reflect (CycleMethod.REFLECT), the gradient pattern will repeat or cycle between the colors. The following code snippet implements the rounded rectangle having a cycle method of reflect (CycleMethod.REFLECT): LinearGradient cycleGrad = LinearGradientBuilder.create() .startX(50) .startY(50) .endX(70) .endY(70) .proportional(false) .cycleMethod(CycleMethod.REFLECT) .stops(new Stop(0f, Color.rgb(0, 255, 0, .784)), new Stop(1.0f, Color.rgb(0, 0, 0, .784))) .build(); 1-7. Creating Menus Problem You want to create standard menus in your JavaFX applications. Solution Employ JavaFX’s menu controls to provide standardized menuing capabilities such as check box menus, radio menus, submenus, and separators. The following are the main classes used to create menus. • javafx.scene.control.MenuBar • javafx.scene.control.Menu • javafx.scene.control.MenuItem The following code calls into play all the menuing capabilities listed previously. The example code will simulate a building security application containing menu options to turn on cameras, sound an alarm, and select contingency plans. primaryStage.setTitle("Chapter 1-7 Creating Menus"); Group root = new Group(); CHAPTER 1 JAVAFX FUNDAMENTALS 28 Scene scene = new Scene(root, 300, 250, Color.WHITE); MenuBar menuBar = new MenuBar(); // File menu - new, save, exit Menu menu = new Menu("File"); menu.getItems().add(new MenuItem("New")); menu.getItems().add(new MenuItem("Save")); menu.getItems().add(new SeparatorMenuItem()); menu.getItems().add(new MenuItem("Exit")); menuBar.getMenus().add(menu); // Cameras menu - camera 1, camera 2 Menu tools = new Menu("Cameras"); tools.getItems().add(CheckMenuItemBuilder.create() .text("Show Camera 1") .selected(true) .build()); tools.getItems().add(CheckMenuItemBuilder.create() .text("Show Camera 2") .selected(true) .build()); menuBar.getMenus().add(tools); // Alarm Menu alarm = new Menu("Alarm"); ToggleGroup tGroup = new ToggleGroup(); RadioMenuItem soundAlarmItem = RadioMenuItemBuilder.create() .toggleGroup(tGroup) .text("Sound Alarm") .build(); RadioMenuItem stopAlarmItem = RadioMenuItemBuilder.create() .toggleGroup(tGroup) .text("Alarm Off") .selected(true) .build(); alarm.getItems().add(soundAlarmItem); alarm.getItems().add(stopAlarmItem); Menu contingencyPlans = new Menu("Contingent Plans"); contingencyPlans.getItems().add(new CheckMenuItem("Self Destruct in T minus 50")); contingencyPlans.getItems().add(new CheckMenuItem("Turn off the coffee machine ")); contingencyPlans.getItems().add(new CheckMenuItem("Run for your lives! ")); alarm.getItems().add(contingencyPlans); menuBar.getMenus().add(alarm); CHAPTER 1 JAVAFX FUNDAMENTALS 29 menuBar.prefWidthProperty().bind(primaryStage.widthProperty()); root.getChildren().add(menuBar); primaryStage.setScene(scene); primaryStage.show(); Figure 1-14 shows a simulated building security application containing radio, checked, and submenu items. Figure 1-14. Creating menus How It Works Menus are standard ways on windowed platform applications to allow users to select options. Menus should also have the functionality of hot keys or keyboard equivalents. Often users will want to use the keyboard instead of the mouse to navigate the menu. First, we create an instance of a MenuBar that will contain one to many menu (MenuItem) objects. The following code snippet creates a menu bar: MenuBar menuBar = new MenuBar(); Secondly, we create menu (Menu) objects that contain one-to-many menu item (MenuItem) objects and other Menu objects making submenus. The following code snippet creates a menu: Menu menu = new Menu("File"); Third, we create menu items to be added to Menu objects, such as menu (MenuItem), check (CheckMenuItem), and radio menu items (RadioMenuItem). Menu items can have icons in them. I don’t showcase this in the recipe, but I encourage you to explore the various constructors for all menu items (MenuItem). When creating a radio menu item (RadioMenuItem), you should be aware of the ToggleGroup CHAPTER 1 JAVAFX FUNDAMENTALS 30 class. The ToggleGroup class is also used on regular radio buttons (RadioButtons) to allow one selected option only. The following code creates radio menu items (RadioMenuItems) to be added to a Menu object: // Alarm Menu alarm = new Menu("Alarm"); ToggleGroup tGroup = new ToggleGroup(); RadioMenuItem soundAlarmItem = RadioMenuItemBuilder.create() .toggleGroup(tGroup) .text("Sound Alarm") .build(); RadioMenuItem stopAlarmItem = RadioMenuItemBuilder.create() .toggleGroup(tGroup) .text("Alarm Off") .selected(true) .build(); alarm.getItems().add(soundAlarmItem); alarm.getItems().add(stopAlarmItem); At times you may want some menu items separated with a visual line separator. To create a visual separator, create an instance of a SeparatorMenuItem class to be added to a menu via the getItems() method. The method getItems() returns an observable list of MenuItem objects (ObservableList