Concepts and Terminology
When you create a JavaFX Application, NetBeans instantiates a default application main class for you, in my case it is named DateCalculator (Listing 1):
Listing 1 – initial main class
Obviously this default class gives you nothing more than a basic framework; a simple Hello World, but it does give you insight into the JavaFX paradigm. If you’re new to JavaFX I strongly recommend gaining a firm understanding of the basic JavaFX concepts including how the UI classes are packaged – while the class hierarchy is intuitive it has some subtlties which can cause some head-scratching if you’re diving into this realm without any formal exposure!
The top-level JavaFX user interface class is called a Stage. Stage descends directly from the Window class, which provides the basic features of a GUI window, including event handlers. Your UI main class is a subclass of Stage.
A Stage hosts a Scene, or as the documentation phrases it, “a Scene is rendered onto a Stage”. Multiple scenes can be applied to a Stage, although only one Scene at a time can be displayed. Very reminiscent of a real-life Stage. It is important to note that Stage and Scene are in two different packages; they are not directly related in a class hierarchy (except as extensions of java.lang.Object, of course). You identify a scene by calling myStage.setScene(myScene);.
In the fashion of typical GUIs, you place GUI objects (other containers, controls, and graphical objects such as labels, shapes, animations) in a Scene. There is a natural hierarchical relationship among the objects in a Scene: for example a top-level Pane object may contain other (child) Panes, each of which may contain labels, text fields, buttons, etc. In JavaFX, this hierarchical content is called a Scene Graph. The top-most object in the Scene Graph hierarchy (the root node) is typically a container such as an AnchorPane. (Note that the out-of-the-box default application in Listing 1 creates a StackPane). Looking at my concept drawing in Figure 1, it’s conceptually straightforward to break it down into a hierarchy of objects.
JavaFX provides a markup language called FXML you can employ to establish the Scene Graph. In principle this is a much cleaner way to lay out your graphical objects, establish their relationships and define their properties and attributes than doing it in procedural code. FXML is XML based, which makes it easy to examine and edit the Scene Graph. FXML uses the concept of a Controller as the functional mechanism that implements the behavior of the FXML document. In other words, a Controller is (most frequently) a Java class that you write to implement the behavior of the objects in your Scene Graph. Going back to Listing 1, you would not typically write code like root.getChildren().add(btn); since that relationship (a button inside of a StackPane) is established in your FXML hierarchy. In effect, FXML allows you to focus on behavior in your code (such as responding to events), and the XML parser handles the layout for you. The styling (visual effects) are most properly rendered using CSS.
SceneBuilder is a visual layout tool that allows you to create your user interface and automatically generate an FXML file of the resulting Scene Graph. Oracle has done a good job of integrating Cascading Style Sheets (CSS) into SceneBuilder, so that features of the interface can be tweaked without recompilation.
Translating my concept diagram into an initial GUI layout using SceneBuilder proved to be a little challenging, even after reading up on the tool documentation. A critical step is to identify your Controller class in SceneBuilder. But it soon became natural to make my updates there and handle any corresponding code changes based on the updated FXML. I will state unequivocally that using SceneBuilder consistently to update the FXML as you enhance and modify the GUI can save you many headaches. Certainly you can generate an FXML file independently of SceneBuilder, or you can simply create graphical components in your source code and define their inter-reationships. You can guess by now that I consider this latter option a “hacking” approach that works fine if you are doing a simple UI or want to create a little sandbox GUI; any “industrial-strength” application requires a rigorous design-and-code strategy and the tool provides you that capability.
I found it very instructive to study the FXML file to appreciate the hierarchical content that SceneBuilder generates (note, I tweaked the file manually on occasion to try out UI changes, but always made the final updates in SceneBuilder).