image
CHAPTER
9
Styling a Control
As shown in Chapter 5, you can style a control in Java code, setting different properties such as the text color of a button. If you need to style a complete application with several different controls, however, this workflow creates a lot of code. JavaFX supports CSS, though, allowing you to style a complete application or control. In this chapter, you’ll learn how to apply CSS styling in JavaFX.
Using Themes to Style an Application
The fastest way to style a complete application in JavaFX is to use a custom theme. By default, all JavaFX applications use the Modena theme to style content (which is the theme applied to all the samples shown in this book). Prior to JavaFX 8, the default theme was Caspian, which is still available as an alternative theme in JavaFX 8. Both themes are considered cross-platform, ensuring a consistent look across all operating systems.
image
NOTE
A theme in JavaFX is defined by a CSS style sheet. Even Modena is defined by a CSS file; the Modena CSS file is part of JavaFX and can be found in the jfxrt.jar file at com/sun/javafx/scene/control/skin/modena/modena.css.
You can change the theme of an application with just one line of code, shown here:
image
image
This code snippet sets the application’s theme to Caspian. JavaFX contains static fields for Modena and Caspian, so you can easily change an application back to Modena, like so:
image
image
The method setUserAgentStylesheet(…) is part of the Application class.
Figure 9-1 shows the sample application created in Chapter 5. This time, the application is styled with Caspian.
image
image
image
FIGURE 9-1.The Caspian theme
As you can see in Figure 9-1, Caspian isn’t as modern as Modena. In addition to the visual appeal, Modena offers a number of benefits that I will cover later in the chapter. It is definitely a best practice to use Modena instead of Caspian, but an application that was developed with JavaFX 2.x and migrated to JavaFX 8 could use Caspian to retain its look, for example.
In addition to Caspian and Modena, the JavaFX community has developed a number of third-party themes. The most popular one is AquaFX (http://aquafx-project.com/). Unlike Modena or Caspian, AquaFX was designed as a native theme, so the theme aims to mimic the look of a specific operating system. In this case, AquaFX styles all default JavaFX controls in the Mac OS Aqua style, so you would use AquaFX for applications that run on a Mac. Figure 9-2 shows the sample application styled by AquaFX.
image
image
image
FIGURE 9-2.The AquaFX theme
As mentioned, each JavaFX theme is defined by a CSS style sheet that contains the styling information for JavaFX controls. To understand how this works, you will now take a deeper look at using CSS in JavaFX.
CSS Basics
Some developers may not have experience using CSS, so I’ll quickly review the basics. Cascading Style Sheets (CSS) is a style sheet language that can be used to define the look and format of documents. It is the default language for styling web pages, and the CSS specification is maintained by the World Wide Web Consortium (W3C). The main goal of CSS is to separate the content from the presentation of documents. Think about a simple static web page; all the content such as tables, text, and hyperlinks can be defined by HTML. To style and format all the containing components, though, you should use CSS. While this is the main use case, CSS can be used in other ways, such as styling text documents or print layouts. In general, CSS describes different style and layout attributes of components, and in JavaFX, it is used to style controls.
Here is a simple CSS definition:
image
image
The CSS snippet defines the font color for an element called headline, and the background-color property is set to the value blue. To bind this definition to the defined element, you use a selector. The selector in the example is #headline, which defines the component that is affected by the given rule. Here are some definitions of CSS terms:
image  CSS has rules that define how a component should be styled.
image  A style sheet contains a set of CSS rules. Usually, this is a CSS file.
image  Each rule has a selector that defines what components should be styled by the rule.
image  Each rule contains a set of properties.
image  For each property, a value is defined.
The given example is a CSS rule that can be used for web development. In JavaFX, the CSS properties have other names than in the CSS definitions for HTML. Each JavaFX property starts with the -fx- prefix. To style a JavaFX control like the previous HTML example, you would use the following rule:
image
image
Note that JavaFX supports the CSS 2.1 specification. That means most of the functionalities in CSS 2.1 can be used in JavaFX. The biggest difference between how the specification is used for web design versus in JavaFX is the -fx- prefix, but there are other minor changes in JavaFX, including the following:
image  There is no @ keyword.
image  Some CSS pseudoclasses and elements such as :first-line, :first-letter, :before, and :after aren’t supported.
image  :active and :focus are replaced by :pressed and :focused.
image  :link and :visited are not supported in general (the Hyperlink control supports :visited).
image  No comma-separated series of font family names in the -fx-font-family property are allowed.
image  The HSB color model is used instead of the HSL model.
An important feature of CSS is its cascading functionality. CSS defines a priority hierarchy for the properties that affect the style of a component. This functionality is useful when you are styling a complete application or view instead of a single control. The CSS rule shown previously defines the background color of an element with the given ID headline. Let’s assume that this element is a JavaFX label in a custom application, and in this application all labels should have gray text. In addition, the headline of the application should have a blue background. Without the cascading functionality, developers must define CSS rules for all Label instances that are used in the application. Here is a short abstract of a CSS style sheet that would do it this way:
image
image
Styling an application this way would be hard because you would need to write a lot of CSS rules, and every time a change request appears, it would be a big problem to change several aspects of the design. If the customer decides to change all labels to a light gray color, for example, you would need to change this in all the CSS rules for all the labels.
To avoid these problems, you can use the cascading functionality of CSS where property declarations are inherited. The following code defines a solution that solves the given problems with only two CSS rules:
image
image
In this code, you define a global rule for all Label instances by using a different selector syntax. The # prefix defines that a selector specifies an ID of a component and affects only those components with the given ID. A dot defines an element type that is a control type in JavaFX. This rule sets the text color of all labels to gray, which includes the headline label. The second rule adds a property to the definition of the headline label. In this rule, the -fx-text-fill property could be overridden to change the text color of this specific label. Later in the chapter, I’ll show different selector types and properties that are supported for JavaFX controls, as well as some best practices in terms of inheritance and cascading.
CSS in JavaFX
JavaFX provides a couple of ways to apply CSS to the nodes of a scene graph. In Chapter 5, you created a simple login dialog. As an example, let’s style this dialog. To do this, let’s change the source code of the application and define some unique IDs for all the components that should be styled, as shown here:
image
image
As a next step, you need a CSS style sheet that defines rules for all the nodes. I won’t describe all the possible properties that can be used in the CSS rules for JavaFX because this is a really huge list, as you might know from web development. You can find a complete overview of all possibilities and the syntax of how CSS can be used in JavaFX in the JavaFX CSS Reference Guide (http://download.java.net/jdk8/jfxdocs/javafx/scene/doc-files/cssref.html). The following code defines a sample style sheet for the login dialog:
image
image
In the style sheet, all the rules are defined by a selector. Each selector starts with the # prefix that defines an ID. Each node that has been defined with the given ID will be styled by the rule, and all the different JavaFX node types can be styled by specified CSS properties.
image
NOTE
All color information in the CSS file is defined by hex values. As you will see later, that is one of many ways that a color can be defined in CSS.
Before looking more closely at the properties and values used, let’s look at the result of the example. Just add the defined style sheet to the JavaFX application using the following code snippet:
image
image
In this line of Java code, the CSS style sheet that is saved in the custom.css file is applied to the scene graph of the application. Figure 9-3 shows the styled login dialog.
image
image
image
FIGURE 9-3.The styled login dialog
As already mentioned, I don’t have room for a complete overview of all these properties, but here are the ones that can be used to style a node:
image-fx-blend-mode
image-fx-cursor
image-fx-effect
image-fx-focus-traversable
image-fx-opacity
image-fx-rotate
image-fx-scale-x
image-fx-scale-y
image-fx-scale-z
image-fx-translate-x
image-fx-translate-y
image-fx-translate-z
imagevisibility
Because all node and control types in JavaFX extend the Node class, all possible controls will support the shown CSS properties by default. As you can see, the Node class defines a lot of CSS properties. These properties can be used in all nodes in JavaFX, and the CSS properties will be inherited. All the properties can hold a value of a given type, and each has a default value. Sometimes, an enumeration is defined for a CSS property, and its value must be a value of the enumeration. An example of this property type is the -fx-alignment property, which is defined by the TextField class. This property can hold one of the following values:
imagetop-left
imagetop-center
imagetop-right
imagecenter-left
imagecenter
imagecenter-right
imagebottom-left
imagebottom-center
imagebottom-right
imagebaseline-left
imagebaseline-center
imagebaseline-right
Other property types that can be used are boolean or number, for example. In addition to the raw values, CSS supports units. Some value types, such as length, define a set of units that can be used as additional information. To define a unit, you must add the keyword of the unit to the value of a property; in these cases, no whitespace is allowed between the number and its unit. The following example defines the font size of a control by using the points unit:
image
image
Table 9-1 defines the units that can be used by the length type. Other value types define units too. You can find all the allowed units in the CSS documentation of JavaFX.
image
TABLE 9-1.Units of the Length Type
Let’s also look at the paint type, which will mostly be used when defining the fill or the border color of a control. This type can define a color, a linear gradient, or a radial gradient. You can find an example for a linear gradient in the following rule:
image
image
The value for the -fx-fill property defines a linear gradient that goes from red to black. The colors of the gradient are specified by red and black values, and CSS contains a huge set of predefined colors that can be used directly in the CSS rules. Figure 9-4 contains an abstract of the list. You can find the complete list in the JavaFX documentation.
image
image
image
FIGURE 9-4.Abstract of CSS colors
image
NOTE
You can also define color information by its RGB values. In this case, the alpha of the color can be specified too. An example for this case is rgba(255,0,0,1).
As mentioned, a property of the paint type can hold a color. Therefore, the following rules would also be correct:
image
image
After looking at the basics of styling with CSS in JavaFX, let’s refactor the CSS style sheet of the first example in this chapter. Here, only ID-based selectors were used, and all colors were specified by hex values. You can refactor the CSS by using class-based selectors and more readable color information, as shown here:
image
image
As you can see in the example, the selector that is defined to style the button is referenced using the ID of the button. Because this rule is needed for only one specific button in this example, it is a best practice to use this kind of selector. Because the sample has more than one Label and TextField that needs styling, you use the class-based selector to define a rule. By doing this, only one rule is needed to style all Label instances instead of one rule for each Label. In addition, keywords are used for most color information. If no keyword is needed, I change the color definition to an RGB value because this format is normally more readable than a hex value.
Another feature of JavaFX is that you can define CSS properties directly in Java code. Because this feature isn’t a best practice, though, developers should usually not use it; I’m only showing it as a reference. You can use the following code snippet in the demo instead of a CSS file. In this case, no CSS file is needed, and the complete styling is done in the Java class.
image
image
Note that because of the cascading functionality of CSS, you can mix all of the approaches shown so far. If you do that, though, you should know the different priorities in the cascade and what rules will overwrite other ones. If you need a lot of custom CSS styling in an application, make sure to plan the CSS structure accurately. If you mix CSS styling in Java code and in CSS files, it can be hard to change a special property later.
image
NOTE
All Node classes in JavaFX can be styled by CSS. The CSS styling functionality is defined in the Styleable interface that is implemented by the Node class.
Using Selectors
In the previous examples, you saw two different CSS selector types. CSS provides a complex syntax to create complex selectors that can be used to define style rules for sets of controls in a JavaFX application. The following examples define different selectors that can be used in JavaFX:
image
image
This defines a rule for a node with the given ID. The Node class provides the id property that must be defined to use the ID-based selector.
The next selector type is the class selector. Here, the dot prefix will be used:
image
image
Most node types in JavaFX already have one defined class. You can find the style classes that are defined by default for different Node classes in the JavaDoc. In addition, you can add a style class to each control. A style class is defined by its name and can be accessed in CSS like the default style classes, as shown here:
image
image
To use the given CSS rule for a node, you must set the style class to the Node instance. Therefore, the Node class contains the getStyleClass() method that returns an ObservableList<String> of all style classes that are defined for the node. An additional style class can be easily added to the list:
image
image
By using style classes, different controls can share a rule. In the following snippet, a CSS rule is defined for a custom class:
image
image
The first rule says that all nodes that have defined the orange-bordered style class and support the -fx-stroke and -fx-stroke-width properties will have an orange border with a line width of 8. The other rule defines a fill color. In Java, you can create some Shape instances that will get styled by the CSS, as shown here:
image
image
Rendering these shapes will result in a blue circle with an orange border and a green circle with an orange border. In this sample, the style classes of both Node instances contain the orange-bordered style class. Therefore, both of them will be rendered with an orange border.
image
NOTE
By convention, style class names that consist of more than one word use a hyphen (-) between words. If a developer creates new style classes for a custom control, the style classes should correspond to class names. For example, the default style class for the ToolBar control is named tool-bar.
If you use a lot of style classes, it is useful to define some rules for a set of style classes. This can be done using the CSS selector syntax too. The following example defines a rule for all nodes that have the dark-control and the big-button class defined:
image
image
image
NOTE
As you will see, it is important not to add a space between the two pseudoclass names in the selector.
In addition to style classes, CSS supports pseudoclasses, which can be used to define a special state of a component. A pseudoclass selector is defined by a colon prefix, as shown in the following sample:
image
image
The defined rule will be used for all Button instances once the hover variable is true. This will happen whenever the mouse cursor enters the node. The node types that are part of JavaFX define a huge set of pseudoclasses. Table 9-2 gives an overview of all pseudoclasses that are defined for the Node class. These pseudoclasses can be used for each node.
image
TABLE 9-2.Pseudoclasses for the Node Class
In addition to these pseudoclasses, each control type defines its specific ones. Table 9-3 describes the pseudoclasses of the IndexedCell class. All cells that are part of a TableView or ListView can be styled by using these pseudoclasses.
image
TABLE 9-3.Pseudoclasses for the IndexedCell Class
By using the shown pseudoclasses, it is simple to define a striped “zebra” effect for all rows of a ListView:
image
image
Once the style sheet that contains the given rules is applied to a JavaFX application that contains TreeView or TableView instances, the rows of these controls will be styled. Figure 9-5 shows an example at run time.
image
image
image
FIGURE 9-5.Styled cells
In addition to the shown selector definitions, you can use the CSS selector syntax to define more complex selectors. For example, maybe you want to change the border of all buttons that are on a toolbar. By using the previously described selectors, you can add a style class to all the Button instances inside the Toolbar instance. With CSS, you can define selectors that look up all Button instances in a Toolbar instance. Here is an example of a CSS rule with the described selector:
image
image
By using the selector, all Node instances that contain the button style class and that are part of the Node hierarchy in the Toolbar with the given ID of my-toolbar will be styled by the rule. Here, a Button instance doesn’t have to be a direct child node of the Toolbar instance. If you want to look up only direct children of the Toolbar, you can use the > sign. By adding this between the two parts of the selector, only direct children will be affected:
image
image
image
NOTE
Using the > sign in a CSS selector will improve performance somewhat. By using it, the complete child hierarchy under the Toolbar control will not need to be scanned. Matching nodes will be searched only in the first hierarchy of children.
You can mix all the shown selector types. Here’s an example:
image
image
By using this rule, all Text nodes that are children of all ListView instances of the application will be rendered with yellow text.
image
NOTE
Most control types in JavaFX include Node instances that can have their own style definition. An example of this is the text of a Button control. The text is internally defined as a Text shape. These inner nodes can be styled by using descendant classes too, as shown in the previous examples. Some examples of these descendant classes are .check-box .label, .check-box .box, or .radio-button .dot.
If you have a basic CSS rule that defines some general styling, you can combine several of the selector types by using a comma. Here is an example that defines the color for the top and bottom arrows in a scroll bar:
image
image
As you can see, the selector of the rule is more complex than the selectors that were shown here. The first line defines all nodes that have defined the increment-arrow class and are direct children of a node that has defined the increment-button CSS class. This node must be a direct child of a node that has defined the scroll-bar CSS class. The second line is similar to the first one and defines the selector for nodes that have defined the decrement-arrow class. The shown CSS classes in this example are defined by JavaFX. The up and down icons of a default JavaFX ScrollBar can be styled like the shown selectors of the code snippet. As stated earlier, a control in JavaFX contains several subnodes that can be styled too. In this example, the ScrollBar of JavaFX contains a node that has the defined CSS class increment-button. When getting started with CSS styling in JavaFX, it’s not easy to find all these internal CSS classes and inner nodes of controls. A good tool to analyze the controls and its inner nodes is the CSS Analyzer, shown in Figure 9-6, that is part of Scene Builder. You can select parts of JavaFX controls with the mouse, and the tool will analyze each one’s pseudoclasses and CSS values.
image
image
image
FIGURE 9-6.CSS Analyzer of Scene Builder
To see how all these different selector types can be used and how the cascading feature of CSS is working, let’s look at an example application. This application contains several buttons that will be styled by CSS. Here is the Java source code of the application:
image
image
The example contains four Button instances that are placed in different parts of the scene graph hierarchy. In addition, all instances have custom IDs defined. In this first step, no CSS and styling are defined. Therefore, the application will be rendered by using the default styling defined by Modena. Figure 9-7 contains all the steps of styling this application that will be discussed in the following text. Without any additional CSS information, the application will appear as in the first dialog of Figure 9-7.
image
image
image
FIGURE 9-7.Styling a JavaFX application, step by step
As a first step, you need a CSS file. Name it customstyle.css and place it in the same package as the application. You can then apply the CSS file as the style sheet for the application using the following code:
image
image
Let’s define the first rule in the CSS file. This rule should affect all buttons that are part of the application, so you can use a class selector, as mentioned earlier. The following code snippet defines the rule:
image
image
When running the application, all buttons will look the same. As defined in the CSS rule, they have a yellow background and a thick blue border. You can see the result in the second dialog of Figure 9-7.
As a next step, all Button instances that are part of the VBox should be in a different style. Therefore, you need to define an additional rule:
image
image
Because the VBox class in JavaFX doesn’t define a default style class, you need to add a class in JavaFX, as shown by the following code snippet:
image
image
You can see the result in the third dialog of Figure 9-7. As shown, all Button instances in the application are part of the children of the VBox, so they have changed slightly. The defined rule doesn’t handle buttons that are direct children of the VBox only; recursively, all children will be found. The defined rule has a higher priority than the first one, and therefore the defined -fx-border-width of the last rule will be used when styling is applied to the control instances.
With the next rule, you want to change only the Button instances that are direct children of the VBox. As shown earlier, you can do this by defining a rule with the > sign:
image
image
By using this rule, you create the first difference in the style of the buttons. Because only the bottomButton is a direct child of the VBox, its border width will be changed. As you can see, this rule has again a higher priority than all the other ones. You can see the result in the fourth dialog in Figure 9-7.
As a next step, you want to change the style of all the Button instances in the toolbar. The ToolBar class in JavaFX already defines a CSS class called tool-bar. You can use this class for the next rule:
image
image
As expected, the style of all buttons in the toolbar has changed after the rule is added. Dialog 5 in Figure 9-7 represents the current state.
Next, all Button instances that are not part of the toolbar should be changed. Therefore, create a new style class called dialog-button. By using this class, you can define a CSS selector. Because you want to change the style of all buttons that are not part of the toolbar, the centerButton and bottomButton instances need this new CSS class. You can apply the class in Java as shown:
image
image
Here is the additional CSS rule:
image
image
You can see the result in the sixth dialog of Figure 9-7. At first, you might think an error has occurred. In the new rule, the -fx-border-width property is defined with a value of 20 that defines very thick borders, but when looking at Figure 9-7, you will notice that the border width hasn’t changed. This isn’t an error. As already mentioned, the cascading feature of CSS is defined by priorities of the CSS rules. The new rule has a lower priority than the two with the .tool-bar.button and .vbox >.button selectors. Because of that, the values of the -fx-border-width property that are defined by these two rules will be used when styling the buttons. These rules don’t define an additional background color or border color, so these values will be extracted from the last rule that is defined by the .dialog-button selector.
image
NOTE
The priority level of CSS rules is defined by the weight of the selector. The weight defines how specific a style is. The more specific style will be used over the less specific one, meaning it has a higher priority. To calculate the weight of a selector, you can use the following formula:
(number of IDs in the selector) × 100 + (number of classes in the selector) × 10 + (pseudoclasses in the selector)
When comparing two rules, the one with the bigger weight of its selector has the higher priority.
As a next step, you want to define a rule that affects only one button. So, you need a selector that defines the Button instance by its ID:
image
image
Because an ID is used in the selector, this CSS rule will have a higher priority than all the other ones, and all properties of the rule will be used for styling. Dialog 7 in Figure 9-7 shows the current state of the dialog.
As a last step, you want to add a CSS property inline in Java code. As already mentioned, this is bad practice, and it is done here only to show how the cascade feature is working and how the priority of inline styling is defined. Therefore, you add the following code snippet to the application:
image
image
As you can see in dialog 8 of Figure 9-7, the button has changed its color. So, this rule that is defined directly in Java has a higher priority than the rules that are defined by CSS. A CSS rule that is defined in Java code always has a higher priority than a rule that is part of a CSS style sheet file. In addition, CSS supports two types of style sheets. The user agent style sheet is the global basic style sheet. In JavaFX, Modena is defined as the default user agent style sheet. All other style sheets, like the one being used in this application, are normal style sheets. These have a higher priority than the user agent style sheet, so the rules in the custom CSS file can override the definitions that are part of Modena. The inline CSS that is part of the Java code always has the highest priority.
image
NOTE
The example shown here was created solely to show the different selector possibilities and priority of rules. This code should not be used for a real application. The cascade of the CSS rules is complex, and many properties are defined several times.
Summary of the Cascading Feature
In the previous section, I discussed a lot of information about the priority of styles and the cascading functionality of CSS. Now, let’s turn to a complete overview.
As you saw in this chapter, you can define styles in style sheets or as inline styles in the Java class. With style sheets, you can set one user agent style sheet for the application by using the setUserAgentStylesheet(…) method of the Application class and add several style sheets to the scene graph by using the getStylesheets() method of the Scene class. In addition, the Parent class provides the getStylesheets() method, so a style sheet can be defined for a subtree of nodes in a scene graph. In addition to the style defined in CSS, you can set a JavaFX property for a node, for instance, setting the text color by using the textFill property of a Button instance. For these types of style definitions, the following rules are valid:
image  A style from a user agent style sheet has a lower priority than setting a JavaFX property.
image  The value of a JavaFX property has a lower priority than a style sheet that is defined for the scene graph.
image  A scene graph style sheet has a lower priority than a style sheet of a parent node.
image  An inline style sheet has the highest priority.
Additionally, several CSS rules defined in one style sheet can affect the same JavaFX node. Here, the following rules are valid:
image  The priority of a rule can be calculated by its selector’s weight.
image  The following formula should be used: (number of IDs in the selector) × 100 + (number of classes in the selector) × 10 + (pseudoclasses in the selector).
image  The rule with the bigger weight has the higher priority.
There is one additional flag that can be used to modify the priority of a CSS property. By adding the !important flag to a value of a CSS property, this value will get the highest priority, as shown here:
image
image
Styling a Chart
In the previous sample, mostly JavaFX control types were styled by CSS. But as mentioned, each node type could be styled with CSS. Therefore, the following example will show how a chart can be styled with CSS. In the demo application, a pie chart is created and shown onscreen.
image
image
Figure 9-8 shows this chart on the top.
image
image
image
FIGURE 9-8.A styled PieChart
As a next step, say you want to style the PieChart with CSS. You create a new style sheet and apply it to the scene graph, as shown here:
image
image
Figure 9-8 shows the result on the bottom. In the style sheet, you will find an additional feature of the CSS support in JavaFX. When styling charts, JavaFX will automatically create CSS classes for all the data parts of the chart. In the example, the classes default-color0, default-color1, and default-color3 can be used to style each of the data sections of the pie chart.
Best Practices for Styling Applications and Controls
When styling an application, it is important not to mix too many CSS style sheets. In most cases, a single CSS file will fit all the needs of an application. Because Modena is defined as the default user agent style sheet in JavaFX, a style sheet for an application must contain only the changes to Modena.
First, apply all global rules. Let’s assume the application must use a special skin for buttons. In this case, a rule that uses the .button pseudoclass should be defined. Here, it is important that all the different states of the control will be tested. For the button type, for example, developers will often need to change the style for states, such as hover, pressed, and focused, so CSS pseudoclasses should be used. If this isn’t done, a user gets no visual feedback when clicking a button. The following example defines how the needed rules for a new button style may look:
image
image
As you can see, the selectors of the rules contain comma-separated lists. By doing this, only a few rules are needed to specify all the needed styling information for a Button and a ToggleButton in the different states.
As a next step, define special types of the controls. In this case, it is best to define custom CSS classes. Let’s say all buttons in menus should have a smaller font. Here, an app-menu-button CSS class is defined that contains a value for the -fx-font-size property:
image
image
If the application contains some special buttons that are used in only one view, you can define these controls with a unique ID. In this case, the ID selector of CSS should be used:
image
image
Doing this for all the needed control types defines a clear hierarchy of styling.
To create an even better overview of the CSS styling and create a more refactorable style sheet, you should use the root style class. The root class is applied to the root node of the scene graph, and properties that are defined in the root style can be used in any other CSS rule. If, for example, you define a style for an application that has blue as its main color, you can define the root style class as shown in the following snippet:
image
image
Here, the property -fx-color-base is defined in the root. The big benefit of this is that the property can be reused in each CSS rule of the style sheet. The following code shows another abstract of the application CSS:
image
image
The -fx-color-base property is reused in two rules here. Once you have extracted all the basic values as global properties to the root rule of a style sheet, it is easy to refactor the styling by changing only one value. Another benefit is that you automatically provide more consistency in the UI because the same values will be used in a lot of control types.
When looking at the Modena CSS file, you will see that a lot of properties are defined in the root section of the style sheet. You can reuse these properties in custom application style sheets or define new values for them. By doing this, you can change the complete style of an application with only a few lines of CSS, as shown here:
image
image
A custom style sheet that contains only these lines will change the complete look of an application. Figure 9-9 shows the sample application that is styled by this style sheet.
image
image
image
FIGURE 9-9.A styled application
image
NOTE
In theory, an application can be styled by multiple style sheets. A style sheet will be added to a scene graph by calling myScene.getStylesheets().add(…). The getStylesheets() method returns a List, and therefore it can hold and manage several style sheets. Suppose you have a default style for all your applications that is wrapped in one default style sheet. If one application needs some additional styles for specific components or the customer needs a special color for all button backgrounds, these features could be implemented in a separate style sheet. In this case, the order of the CSS style sheets in the list defines its priority. When possible, though, it is a best practice to define the styling of an application in a single style sheet.
A final best practice for developers creating huge CSS style sheets is the proper use of the derive(…) and ladder(…) functions. These two functions can be used to define color values in CSS. When thinking about a style for a complete application, you will mostly use some basic colors that specify the color theme of the application. In general, these colors will be used in several modifications in the UI of the application. For instance, maybe the basic color for an application is a light blue. In this case, the background of all buttons will be defined as lightblue, and the border of all buttons should appear in a darker blue. In this case, the derive(…) function can be used to derive the border color from the base color. To do this, the derive(…) function takes a color and computes a brighter or darker version of that color. The second parameter of the derive(…) function is the brightness offset that can be defined in a range from –100% to 100%. You can use the derive(…) function as a value for a CSS property, as shown in the following snippet:
image
image
In this case, only the value of the -fx-base property needs to be changed to affect all defined colors. In addition to the derive(…) function, the ladder(…) function can be used to interpolate between colors. Here, a gradient must be specified, and the brightness of the provided color parameter is used to look up a color value within that gradient. The calculated color depends on the brightness of the passed color. At 0 percent brightness, the returned color will be the start color of the gradient. At 100 percent brightness, the color at the 1.0 end of the gradient is used. Here’s an example:
image
image
In the CSS style sheet, the ladder(…) function is used to define the text color for two buttons. You create these buttons in a JavaFX application without defining any additional parameters next to their IDs:
image
image
When running the application, the two buttons will have different text colors. The color of the text fits perfectly to the light and dark backgrounds of the buttons, as shown in Figure 9-10.
image
image
image
FIGURE 9-10.Result of the ladder() function
By using the brightness of the background color, the ladder(…) function calculates the perfect color for the text.
With the two methods shown here, it is easy to define global base colors in CSS and use derived colors in specific rules.
An Interview with Claudine Zillmann, software developer at maredit GmbH
Hi, Claudine. Many JavaFX developers know you as a CSS expert for JavaFX styling and the maintainer of AquaFX. Therefore, I think you can add some useful information and tips about styling to the more general information about CSS mentioned in this book. But before we start, can you please introduce yourself and how you came to JavaFX and CSS?
Hello, Hendrik, it’s a pleasure to contribute to your work with an interview and share tips and knowledge on this topic.
Right now, I work at maredit GmbH as one of three lead developers for e-commerce projects and specialize in developing controls with our recently created web framework.
But to introduce myself, I take a step further back in time.
I will start with my first steps in styling and HTML. At the beginning, I tried some things just for fun, using 1x1-pixel images or marquee tags. Soon, school projects made me concentrate on using CSS and what it stands for. You find out a lot of benefits and concepts, such as the box model and separation of markup and styling in general. But I realized that those components were not comfortable. Especially proper usage of positioning made me mad at times.
During my studies at university, I concentrated on Java development and started to work in a company with a client-server application, specializing on development of the Swing client for seven years. In that time, JavaFX came up and became a successor of Swing. Soon, the idea of AquaFX was born at the completion of my degree. It was like, “Hey, I think JavaFX really rocks, and I want a deep dive in that technology. JavaFX is young and could need contributions. Let’s create a skin!” Since that time, JavaFX has been my hobby and my favorite UI framework.
It sounds to me as you played with most of the different layout solutions that appeared over the last few years, beginning with a 1-pixel blank.gif to the CSS styling that we have today with Bootstrap and JavaFX CSS styling. Can you tell me what are the biggest differences between CSS styling for web content and JavaFX content?
The differences are not really that big, on the one hand. On the other hand, they are immense (but control-based web design comes up more and more). In an exaggerated way, I think I was lucky by not getting too serious in web design, so I do not miss a lot of stuff that might be possible with web CSS. JavaFX adapted the CSS standard and adjusted it for its UI controls. So, you have nodes (a box model), which can be styled with colors, borders, padding, effects, and so on, and which also can inherit styles by parent nodes, as known from conventional web design. If you know those concepts and the possibilities that CSS offers, it is not hard to style JavaFX applications. You just have to be aware of some tiny things:
image  The naming is different: not background-color but -fx-background-color.
image  You are within a control, especially when it’s about positioning. This is the part where you should not forget about the concept of layout managers in UI frameworks.
image  Not everything is possible with JavaFX CSS, but almost. Just stick to the reference guide before you start. That will help.
image  Things that might seem impossible are not really impossible because you also might realize them in a programmatic way.
All in all, it is pretty similar. Like in web-based design, all those possibilities can be used in a good and a “less good” way. This could cause ugly code, unwanted visual results, or performance issues.
In conclusion, JavaFX combines the strength of UI frameworks with web design, so cool results can be achieved straightforwardly, even if you do not know CSS very well or at all.
Let me ask a last general CSS question before we talk about CSS for JavaFX and your AquaFX project. There are different ways you can apply CSS: by using several style sheets, defining all CSS rules in one big style sheet, or adding all styles inline, for example. Do you have any tips or a best-practice workflow for how developers should organize their CSS styles?
There is no general best-practice workflow that fits every need. I think the answer is, “It depends.” You have to ask yourself a couple of questions to find the proper organization of styles for your project. For example:
image  Do I want to reuse styles?
image  Can some characteristics be generalized?
image  Should colors/sizes vary? Or are there other variations?
So, define the individual requirements of your own project, and then you can decide how to realize it.
Generally, if you just want to try something or modify some tiny things, inline styles might be enough. I’m not a friend of that technique at all, though.
If you create a set of your own controls, try to put all general definitions in one style sheet and add individual styles for each control. For a complete skin, I used one style sheet because you touch every single control.
Thanks for this hint. Let’s change the focus and talk about JavaFX in combination with CSS. Why do you think each JavaFX developer should know CSS and use it when developing JavaFX applications?
This answer is pretty simple: because it makes development so much easier. The times of programmatic styling and drawing each component are over. Formatting, colors, and style information shouldn’t live within your code. Why not use proven concepts of web development and apply them? Your application gets much more flexible as well. On top of that, CSS is no mystery and not that hard to learn. Does it need more reasons?
The CSS support in JavaFX is based on CSS 2.1 and adds some useful functions like derive(…) and ladder(…). These functions are normally not part of CSS and help a developer to create flexible and more readable CSS definitions. Do you have some other hints how a developer can create readable and flexible CSS rules?
There are several hints to achieve readable and flexible CSS definitions. I think the five most important tips are
image  Get to know all possibilities JavaFX already ships with by default. Take more than one look at the JavaFX CSS Reference Guide. It tells you about all those cool functions JavaFX offers for CSS.
image  The other important thing to address is the source of the Modena skin. When you look at the CSS shipped with JavaFX, there are no more mysteries about the usage of CSS.
image  Make your CSS flexible by learning how to use selectors properly. The smarter your selection is, the more efficient the parsing of the scene graph is.
image  When it comes to colors, use looked-up colors. Looked-up colors enable a global definition of colors in some sort of variable. This then can be used in the whole CSS and, for example, altered by the functions derive(…) and ladder(…) you mentioned. With that approach, you can use a few color definitions that are held centrally and avoid a complete revision of all CSS definitions when changing the whole color scheme. This concept could even be widened by implementing your own functions. As I mentioned, almost everything is possible with JavaFX.
Many web developers started to use a dynamic style sheet language like LESS to optimize their CSS style sheets. Do you know whether workflows like this can be used in JavaFX, too?
Oh, well, actually Tom Schindl has already experimented with LESS and JavaFX. He published a little blog post about his thoughts and experiments in this promising area. If you want to know more, read it at http://tomsondev.bestsolution.at/2013/08/07/using-less-in-javafx/. This trend is really noteworthy.
Let’s talk about AquaFX. With this project, you created a complete skin for all the basic JavaFX controls. Can you share some of the pitfalls with that you were confronted with and experiences that you earned while developing the theme?
Sure, I can. But where to start? I think, with the concept. One of the first questions I asked myself was, do I base the skin on an existing JavaFX skin, or shall I create it independently? Since AquaFX will explicitly be the look and feel of OS X for JavaFX, it couldn’t be dependent on future changes in the base skin. So, adjusting the base skin was no option, which means that every control had to be styled from scratch.
When it comes to styling controls, this is pure work and good eyes. One pitfall can be the vertical alignment of text. If you work a lot with padding, check your new controls next to each other. Some other tips for all kinds of questions can be found on my slides, loaded up on SlideShare: http://de.slideshare.net/ClaudineZillmann/lets-get-wetbestpracticesforskinningjavafxcontrols.
Thank you very much for this interview. Let me ask one last question: Are you planning to create some other JavaFX themes in the future?
Thank you very much for conducting this interview. It is always a pleasure. To your last question: Well, yes, the next skin, FlatterFX, is still in progress and will be published when it is finished. I guess the next steps are maybe some experiments with LESS and some optimization of AquaFX. After that, we will see what the community might ask for.
Summary
As you saw in this chapter, the CSS support in JavaFX is detailed and could therefore warrant a book of its own. This chapter covered the basics, so you should be able to create style sheets based on these practices and features. It is also important to take a deeper look at the CSS documentation of JavaFX as you begin working with CSS; all the classes, pseudoclasses, and properties are described in the documentation.
By using CSS to style a JavaFX application, you can create a perfect separation between the styling and the logic of an application. By using CSS and FXML in combination, only the business and controller logic of an application must be implemented in Java. All the layout and styling topics can be defined in languages that fit your needs. If you’ve already used CSS for web development, you should have no trouble becoming familiar with the functions covered in this chapter. However, the benefits of using CSS are so important that everyone should use it. Your application will be more structured, and changes in the style of an application can be defined quickly if the CSS style sheet of the application is well structured.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.205.99