JavaFX improvements in Java SE 8u40

Learn about JavaFX 8u40's support for accessibility, standard and custom dialogs, a spinner control, and text formatting.

Oracle's Java SE 8u40 update release notes document identifies several new JavaFX features in its discussion of this update's various enhancements and bug fixes. The new features include accessibility support, standard and custom dialogs, a spinner control, and support for text formatting. In this post, I introduce you to these features.

Accessibility

Q: What is accessibility?

A: Accessibility is the degree to which a product, device, service, or environment is available to as many people as possible. For example, graphical user interfaces can be made more accessible by providing screen reader devices, which speak graphical content, to blind people.

Q: In what ways does JavaFX support accessibility?

A: JavaFX supports accessibility on Windows and Mac OS X platforms in the following ways:

  • By providing support for reading JavaFX controls via a screen reader (e.g., Apple's VoiceOver for the Mac, Microsoft's Narrator for Windows, Freedom Scientific's JAWS for Windows)
  • By providing JavaFX controls that are traversable using the keyboard
  • By supporting a special high-contrast mode that makes controls more visible to users -- this mode is activated on Windows by pressing Alt+Left Shift+Print Screen

Q: How does JavaFX support accessibility?

A: JavaFX supports accessibility by adding the following properties to the javafx.scene.Node class:

  • accessibleRoleProperty: the node's accessible role, which is a value of the javafx.scene.AccessibleRole enumerated type that identifies the kind of control to the screen reader (e.g., AccessibleRole.BUTTON or AccessibleRole.MENU). The screen reader uses a node's role to identify supported attributes and actions.
  • accessibleRoleDescriptionProperty: the node's role description, which is a string. Normally, when a role is provided for a node, the screen reader speaks the role along with the node's contents. When this value is set, it's possible to override the default, which is useful because the set of roles is predefined. For example, it's possible to set a node's role to a button while having the role description be arbitrary text.
  • accessibleTextProperty: the node's accessible text, which is a string. This property identifies the text that the screen reader will speak. If a node normally speaks text, that text is overridden. For example, a button usually speaks using the text in the control but will no longer do so when this property is set. This property is especially useful for non-text-oriented controls such as image view.
  • accessibleHelpProperty: the node's accessible help, which is a string. The help text provides a more detailed description of the node's accessible text. By default, if the node has a tool tip, this text is used.

Additionally, javafx.scene.control.Label's labelFor property is used by a screen reader to provide more information to the user. For example, suppose a text field contains Joe and labelFor connects this text field to a label that states First Name. When the text field receives focus, the screen reader will utter "First name, editable text, Joe".

Finally, JavaFX provides a more advanced API for interacting with the screen reader and accessing accessibility state. You would use this API to introduce accessibility support to your own controls or other nodes.

The advanced API includes the javafx.scene.AccessibleAction and javafx.scene.AccessibleAttribute enumerated types along with the following Node methods:

  • Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters)
  • void executeAccessibleAction(AccessibleAction action, Object... parameters)
  • void notifyAccessibleAttributeChanged(AccessibleAttribute attributes)

An exploration of the advanced API is beyond the scope of this article.

Q: I would like to try out JavaFX's accessibility support. Can you provide a simple JavaFX application that lets me try out and experiment with accessibility?

A: I've created a TempVerter application for converting a temperature to Fahrenheit or Celsius. Listing 1 presents its source code.

Listing 1. TempVerter.java

import javafx.application.Application;

import javafx.event.ActionEvent;

import javafx.geometry.Insets;

import javafx.scene.Scene;

import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;

import javafx.scene.layout.HBox;

import javafx.stage.Stage;

public class TempVerter extends Application
{
   @Override
   public void start(Stage primaryStage)
   {
      TextField txtDegrees = new TextField();
      Label lblDegrees = new Label("Degrees:");
      lblDegrees.setLabelFor(txtDegrees);
      Button btnToC = new Button("To C");
      btnToC.setOnAction(ae -> 
                         {
                            try
                            {
                               String input = txtDegrees.getText();
                               double deg = Double.parseDouble(input);
                               txtDegrees.setText("" + ((deg - 32) * 5 / 9.0));
                            }
                            catch (NumberFormatException nfe)
                            {
                               new Alert(AlertType.ERROR, 
                                         "Valid number expected").showAndWait();
                            }
                         });
      Button btnToF = new Button("To F");
      btnToF.setOnAction(ae -> 
                         {
                            try
                            {
                               String input = txtDegrees.getText();
                               double deg = Double.parseDouble(input);
                               txtDegrees.setText("" + (deg * 9 / 5.0 + 32));
                            }
                            catch (NumberFormatException nfe)
                            {
                               new Alert(AlertType.ERROR, 
                                         "Valid number expected").showAndWait();
                            }
                         });
      HBox hboxForm = new HBox(10);
      hboxForm.setPadding(new Insets(10, 10, 10, 10));
      hboxForm.getChildren().addAll(lblDegrees, txtDegrees, btnToC, btnToF);
      Scene scene = new Scene(hboxForm);
      primaryStage.setScene(scene);
      primaryStage.setResizable(false);
      primaryStage.setTitle("TempVerter");
      primaryStage.show();
   }
}

Listing 1 describes an application whose user interface consists of a label, a text field, and a pair of buttons. The application is pretty basic so I don't have much to say about the source code. However, you will notice the creation of a pair of Alert-based dialogs in the catch handlers of the lambdas associated with the button onAction properties. These dialogs are another new JavaFX feature, which I'll discuss in the next section.

Compile Listing 1 as follows:

javac TempVerter.java

Before running the application, you need to install a screen reader. For my 64-bit Windows 7 platform, I'm using Microsoft's pre-installed Narrator software. To run this program, I enter narrator in the Start menu's Search programs and files text field. In response, I observe the window shown in Figure 1. I also hear a feminine voice describing the window and its contents.

1 2 3 4 Page 1
Notice to our Readers
We're now using social media to take your comments and feedback. Learn more about this here.